moq | Interface mocking tool for go generate | Mock library
kandi X-RAY | moq Summary
Support
Quality
Security
License
Reuse
Currently covering the most popular Java, JavaScript and Python libraries. See a Sample Here
moq Key Features
moq Examples and Code Snippets
Trending Discussions on moq
Trending Discussions on moq
QUESTION
I'm new to Unit testing and I'm trying to learn how to do it.
I'm using Moq to Mock the dependencies.
Here's my Testing class:
using Microsoft.AspNetCore.Mvc;
using Moq;
using scholarship.Controllers;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Xunit;
namespace Testing
{
public class InternControllerTests
{
private Mock _internService = new Mock();
[Theory]
[InlineData("00000000-0000-0000-0000-000000000001")]
[InlineData("00000000-0000-0000-0000-000000000002")]
public void Delete_Intern(Guid id)
{
InternsController internsController
= new InternsController(_internService.Object);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual is OkObjectResult);
}
[Theory]
[InlineData("00000000-0000-0000-0000-000000000000")]
[InlineData("00000000-0000-0000-0000-000000000005")]
public void Delete_Intern_NotFound(Guid id)
{
InternsController internsController
= new InternsController(_internService.Object);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual is NotFoundObjectResult);
}
}
}
the service:
using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace scholarship.Services.Class
{
public class InternCollectionService : IInternService
{
public static List _interns = new List
{
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000001"), FirstName = "Octavian", LastName = "Niculescu", DateOfBirth=new DateTime(2001,01,01)},
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000002"), FirstName = "Andrei", LastName = "Popescu", DateOfBirth=new DateTime(2002,01,01)},
new Intern { ID = new Guid("00000000-0000-0000-0000-000000000003"), FirstName = "Calin", LastName = "David", DateOfBirth=new DateTime(2003,01,01)},
};
public bool Create(Intern model)
{
_interns.Add(model);
return true;
}
public bool Delete(Guid id)
{
int index = _interns.FindIndex(intern => intern.ID == id);
if (index == -1)
{
return false;
}
_interns.RemoveAt(index);
return true;
}
public Intern Get(Guid id)
{
return (from intern in _interns
where intern.ID == id
select intern).FirstOrDefault();
}
public List GetAll()
{
return _interns;
}
public bool Update(Guid id, Intern model)
{
int index = _interns.FindIndex(intern => intern.ID == id);
if (index == -1)
{
return false;
}
model.ID = id;
_interns[index] = model;
return true;
}
}
}
the controller
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using scholarship.Models;
using scholarship.Services.Interface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace scholarship.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class InternsController : ControllerBase
{
IInternService _internService;
public InternsController(IInternService internService)
{
_internService = internService ?? throw new ArgumentNullException(nameof(internService));
}
[HttpGet]
public IActionResult GetInterns()
{
return Ok(_internService.GetAll());
}
[HttpGet("{Id}", Name = "GetIntern")]
public IActionResult GetIntern([FromRoute] Guid Id)
{
Intern? intern = _internService.Get(Id);
if(intern == null)
{
return NotFound();
}
return Ok(intern);
}
[HttpPost]
public IActionResult AddIntern([FromBody] Intern intern)
{
intern.ID = Guid.NewGuid();
_internService.Create(intern);
return CreatedAtRoute("GetIntern", new { ID = intern.ID }, intern);
}
[HttpPut("{id}")]
public IActionResult UpdateIntern([FromBody] Intern intern, Guid id)
{
if (intern == null)
{
return BadRequest("Intern cannot be null");
}
_internService.Update(id, intern);
return Ok();
}
[HttpDelete("{id}")]
public IActionResult DeleteIntern(Guid id)
{
bool deleted = _internService.Delete(id);
if (deleted == false)
{
return NotFound("Intern cannot be found");
}
return Ok();
}
}
}
The project is a very small one, I used it to start learning .net.
Now I want to learn Unit Testing, and I'm trying to learn Unit Testing.
The Delete tests fail.
I think this happens because by mocking the service, there is no list with data like in the service.
So, how should I make the Delete tests work? Should I somehow mock that list too? (I don't know how)
Thanks.
ANSWER
Answered 2022-Apr-10 at 10:29Although it is not best practice to test everything in one shoot, you can change your code as per below and test by status code with your inline data and hardcoded return type:
[Theory]
[InlineData("00000000-0000-0000-0000-000000000001", true, 200)]
[InlineData("00000000-0000-0000-0000-000000000002", true, 200)]
[InlineData("00000000-0000-0000-0000-000000000000", false, 404)]
[InlineData("00000000-0000-0000-0000-000000000005", false, 404)]
public void Delete_Intern(Guid id, bool expectedReturn, int expectedStatusCode)
{
InternsController internsController
= new InternsController(_internService.Object);
_internService.Setup(x => x.Delete(It.Is(x => x.Equals(id)))).Returns(expectedReturn);
var actual = internsController.DeleteIntern(id) as ObjectResult;
Assert.True(actual.StatusCode == expectedStatusCode);
}
However, you can read the How to use Moq and xUnit for Unit Testing Controllers in ASP.NET Core which I think is a good practice.
QUESTION
I have a unit test where I am using Moq and Fluent Assertions:
[Fact]
public void GetSymbols_ShouldSetSucceedToTrue_WhenSecondAttemptSucceed()
{
string selectedFileName = "testFileName.txt";
string[] expectedResult = new string[] { "testSymbol1", "testSymbol2" };
Mock mockFileDialogService = new Mock();
mockFileDialogService.SetupSequence(m => m.ShowDialog()).Returns(false).Returns(true);
mockFileDialogService.Setup(m => m.FileName).Returns(selectedFileName);
Mock mockFileService = new Mock();
mockFileService.Setup(m => m.ReadAllLines(selectedFileName)).Returns(expectedResult);
SymbolsProviderFromFile spff = new SymbolsProviderFromFile(mockFileDialogService.Object, mockFileService.Object);
// Act
spff.GetSymbols();
IEnumerable result = spff.GetSymbols();
// Assert
using (new AssertionScope())
{
result.Should().Equal(expectedResult);
spff.Succeed.Should().BeTrue();
}
}
I would like to check the second call of my method. Unfortunately when I debug this code, the spff.GetSymbols()
method is only called once and it is called on the result.Should().Equals(expectedResult)
line when the result is checked. There is some kind of a lazy loading here - the method is only called when the result is needed. Why is it not called immediately in the spff.GetSymbols()
line? How can I change this behavior and how can I call testing method twice in unit test?
ANSWER
Answered 2022-Apr-01 at 06:18Problem has been resolved thanks to @Dennis Doomen.
An issue about not executing method immediately was in the implementation of the spff.GetSymbols()
method which uses yield return
so it wasn't really related to unit testing.
QUESTION
I am using EF Core 6.0.x + NUnit + Moq. Below example is strongly anonymized, the real scenario actually makes sense.
I have a DbContext:
public class MyDbContext : DbContext
{
public virtual DbSet Foos { get; set; }
public MyDbContext(DbContextOptions options) : base(options) { }
public virtual void PreSaveActions()
=> throw new NotImplementedException(); //Here I've got something that must be done pre-save.
public override int SaveChanges()
{
PreSaveActions();
return base.SaveChanges();
}
}
I have a method similar to this:
public class SafeRemover
{
private readonly IDbContextFactory _contextFactory;
public SafeRemover(IDbContextFactory contextFactory)
{
_contextFactory = contextFactory;
}
public int SafeRemove(string name, int barId)
{
using var context = _contextFactory.CreateDbContext();
var itemToRemove = context.Foos.SingleOrDefault(foo => foo.BarId == barId && foo.Name == name);
if (itemToRemove != null)
context.Foos.Remove(itemToRemove);
return context.SaveChanges();
}
}
DependencyInjection registrations:
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
.ConfigureServices((_, services) =>
{
services
.AddDbContextFactory(options => options.UseSqlServer(configuration.GetConnectionString("MyDbContext")))
.AddSingleton();
}).Build();
I want to unit test that this method removes or not certain entities from the given set in database context.
Attempt 1 InMemoryDatabase + mocks:private static readonly object[] _safeRemoveSource =
{
new TestCaseData("Foo1", 1, new List()).SetName("SafeRemove_FooExists_FooRemoved"),
new TestCaseData("Foo2", 1, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentNameExists_FooNotRemoved"),
new TestCaseData("Foo1", 2, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentBarIdExists_FooNotRemoved"),
}
[TestCaseSource(nameof(_safeRemoveSource))]
public void SafeRemoveTest(string name, int barId, IList expectedFoos)
{
var options = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
var contextMock = new Mock(options) {CallBase = true};
contextMock.Setup(context => context.PreSaveActions());
var contextFactoryMock = new Mock>();
contextFactoryMock.Setup(factory => factory.CreateDbContext()).Returns(contextMock.Object);
var safeRemover = new SafeRemover(contextFactoryMock.Object);
safeRemover.SafeRemove(name, barId);
var actualFoos = contextMock.Object.Foos.ToList();
Assert.AreEqual(expectedFoos.Count(), actualFoos.Count());
for (var i = 0; i < expectedFoos.Count(); i++)
Assert.That(expectedFoos[i].Name.Equals(actualFoos[i].Name) && expectedFoos[i].BarId == actualFoos[i].BarId);
}
When I use the InMemoryDatabase
I am unable to check the value of contextMock.Object.Foos.ToList()
after invoking saveRemover.SafeRemove(name, barId)
because the contextMock.Object
is already disposed:
Attempt 2 Mocked dbset and callbacks:System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur is you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'Context'.
private static readonly object[] _safeRemoveSource =
{
new TestCaseData("Foo1", 1, new List()).SetName("SafeRemove_FooExists_FooRemoved"),
new TestCaseData("Foo2", 1, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentNameExists_FooNotRemoved"),
new TestCaseData("Foo1", 2, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentBarIdExists_FooNotRemoved"),
}
[TestCaseSource(nameof(_safeRemoveSource))]
public void SafeRemoveTest(string name, int barId, IList expectedFoos)
{
var actualFoos = new List { new Foo { Name = "Foo1", BarId = 1 } };
var options = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
var foosMock = new Mock> {CallBase = true};
foosMock.Setup(set => set.Remove(It.IsAny())).Callback(foo => actualFoos.Remove(foo));
var contextMock = new Mock(options) {CallBase = true};
contextMock.Setup(context => context.PreSaveActions());
contextMock.Setup(context => context.Foos).Returns(foosMock.Object);
var contextFactoryMock = new Mock>();
contextFactoryMock.Setup(factory => factory.CreateDbContext()).Returns(contextMock.Object);
var safeRemover = new SafeRemover(contextFactoryMock.Object);
safeRemover.SafeRemove(name, barId);
Assert.AreEqual(expectedFoos.Count(), actualFoos.Count());
for (var i = 0; i < expectedFoos.Count(); i++)
Assert.That(expectedFoos[i].Name.Equals(actualFoos[i].Name) && expectedFoos[i].BarId == actualFoos[i].BarId);
}
Everything seems to work as expected instead of one thing... I'm getting NotSupportedException on SingleOrDefault
method in above configuration of mocks:
Attempt 3 (successfull)System.NotSupportedException : Specified method is not supported.
I went back to the attempt 1 and removed using
clause. Now it seems to work as expected, but am I safe to do so? Would DI container be smart enough to leave it entirely for him? I can't find anything about that in the docs and I'm not that good at profiling to check it comprehensively.
I've used InMemoryDatabase with derivered TestMyDbContext
class. Still without success. I've got ObjectDisposedException
on the following line: var actualFoos = context.Foos.ToList();
TestMyDbContext:
public class TestMyDbContext : MyDbContext
{
public override void PreSaveActions() {}
}
Unit test:
private static readonly object[] _safeRemoveSource =
{
new TestCaseData("Foo1", 1, new List()).SetName("SafeRemove_FooExists_FooRemoved"),
new TestCaseData("Foo2", 1, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentNameExists_FooNotRemoved"),
new TestCaseData("Foo1", 2, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentBarIdExists_FooNotRemoved"),
}
[TestCaseSource(nameof(_safeRemoveSource))]
public void SafeRemoveTest(string name, int barId, IList expectedFoos)
{
var initialFoos = new List { new Foo { Name = "Foo1", BarId = 1 } };
var options = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
using var context = new TestMyDbContext(options);
context.Foos.AddRange(actualFoos);
context.SaveChanges();
var contextFactoryMock = new Mock>();
contextFactoryMock.Setup(factory => factory.CreateDbContext()).Returns(context);
var safeRemover = new SafeRemover(contextFactoryMock.Object);
safeRemover.SafeRemove(name, barId);
var actualFoos = context.Foos.ToList();
Assert.AreEqual(expectedFoos.Count(), actualFoos.Count());
for (var i = 0; i < expectedFoos.Count(); i++)
Assert.That(expectedFoos[i].Name.Equals(actualFoos[i].Name) && expectedFoos[i].BarId == actualFoos[i].BarId);
}
ANSWER
Answered 2022-Mar-31 at 11:49I've got an answer from one of NUnit collaborator under this thread: https://github.com/nunit/nunit/issues/4090
Long story short - make sure that you are creating new DbContext instance each time when it's needed and just reuse the "options" to point out on which InMemory database should they operate:
private static readonly object[] _safeRemoveSource =
{
new TestCaseData("Foo1", 1, new List()).SetName("SafeRemove_FooExists_FooRemoved"),
new TestCaseData("Foo2", 1, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentNameExists_FooNotRemoved"),
new TestCaseData("Foo1", 2, new List { new Foo { Name = "Foo1", BarId = 1 } }).SetName("SafeRemove_FooWithDifferentBarIdExists_FooNotRemoved"),
}
[TestCaseSource(nameof(_safeRemoveSource))]
public void SafeRemoveTest(string name, int barId, IList expectedFoos)
{
var initialFoos = new List { new Foo { Name = "Foo1", BarId = 1 } };
var options = new DbContextOptionsBuilder().UseInMemoryDatabase(Guid.NewGuid().ToString()).Options;
using var context = new TestMyDbContext(options);
context.Foos.AddRange(actualFoos);
context.SaveChanges();
var contextFactoryMock = new Mock>();
contextFactoryMock.Setup(factory => factory.CreateDbContext()).Returns(new TestMyDbContext(options));
var safeRemover = new SafeRemover(contextFactoryMock.Object);
safeRemover.SafeRemove(name, barId);
var actualFoos = new TestMyDbContext(options).Foos.ToList();
Assert.AreEqual(expectedFoos.Count(), actualFoos.Count());
for (var i = 0; i < expectedFoos.Count(); i++)
Assert.That(expectedFoos[i].Name.Equals(actualFoos[i].Name) && expectedFoos[i].BarId == actualFoos[i].BarId);
}
QUESTION
Moq doesn't match the mocked method.
Exception:
Exception thrown: 'Moq.MockException' in Moq.dll: 'IMongoRepository.FindByVrcId("b4cb3139-90aa-4477-979b-d893e3317386") invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.'
This is my unit test:
public class OfferHandlerTest : TestBase
{
Mock repositoryMock = new Mock(MockBehavior.Strict);
OfferHandler? offerHandler;
[Fact]
public void HandleTest()
{
JObject? offerFullDocument = null;
using (var sr = new StreamReader("Data/offer_full_document.json"))
{
var reader = new JsonTextReader(sr);
offerFullDocument = JObject.Load(reader);
}
var kafkaPayload = new KafkaMessagePayloadSourceConnector();
kafkaPayload.OperationType = Constants.Mongo_OperationType_Update;
kafkaPayload.FullDocument = offerFullDocument;
OfferService service = new OfferService(repositoryMock.Object);
offerHandler = new OfferHandler(service, this.ServiceConfiguration);
offerHandler.Handle(kafkaPayload);
DHOffer offer = new DHOffer();
offer.Version = 1;
// THIS SETUP FAILS
repositoryMock.Setup(s => s.FindByVrcId(It.IsAny())).Returns(It.IsAny());
repositoryMock.Verify(s => s.FindAndUpdate(It.IsAny()), Times.Once);
}
}
This is the handle method:
public void Handle(KafkaMessagePayloadSourceConnector kafkaPayload)
{
VRCOffer offer = kafkaPayload!.FullDocument!.ToObject()!;
if (kafkaPayload!.OperationType!.Equals(Constants.Mongo_OperationType_Update))
{
offerService.updateOfferStatus(OfferMapper.MapToDataHubModel(offer), offer.MasterId);
}
}
And finally the service method:
public class OfferService
{
private readonly IMongoRepository offerRepository;
public OfferService(IMongoRepository offerRepository)
{
this.offerRepository = offerRepository;
}
internal void updateOfferStatus(DHOffer offer, string vrcMasterId)
{
// THIS SHOULD RETURN MOCKED OBJECT
DHOffer existingOffer = offerRepository.FindByVrcId(vrcMasterId);
existingOffer.ModifiedDate = DateTime.Now.ToString();
existingOffer.AdditionalInformation.Status = offer?.AdditionalInformation?.Status!;
offerRepository.FindAndUpdate(existingOffer);
}
}
I tried using It.IsAny()
in the Return()
method but I get the same exception.
ANSWER
Answered 2022-Mar-16 at 14:49Your issue is that you are running the Moq setup after the mocked object has been used. By then it's already too late. You just need to run the .Setup(...)
commands at the start.
It's also worth noting that using a shared mock can be problematic if multiple tests need the setups to be different. Some tools can run tests in parallel which may screw things up, or in a different order which can cause things to be more brittle.
QUESTION
Require help in mocking Dependency Injection GetService
method in ASP NET Core 5, with MOQ - 4.16.1, Nunit 3
Here is my production code:
class SomeClass(){
IServiceProvider serviceProvider;
public SomeClass(IServiceProvider serviceProvider){
this.serviceProvider = serviceProvider;
}
void MethodHello(UserType type) {
var service = serviceProvider.GetService>();
Console.WriteLine(service(type).GetAge());
}
}
public enum UserType {
Male,
Female
}
My Unit tests:
class SomeClassTest{
Mock mockMale = new();
Mock mockFemale = new();
Mock serviceProvider = new Mock(MockBehavior.Loose);
[SetUp]
public SetUp(){
Func func = (type) => {
if (type == UserType.Male)
return mockMale.Object;
else return mockFemale.Object;
};
serviceProvider.Setup(x => x.GetService(typeof(Func)))
.Returns(func);
mockMale.SetUp(x => x.GetAge()).Returns(20);
mockFemale .SetUp(x => x.GetAge()).Returns(50);
}
[Test]
public void Test_MethodHello(){
new SomeClass(serviceProvider.Object).MethodHello(UserType.Male);
}
}
With this, MOQ framework throws exception: Object of type 'System.RuntimeType' cannot be converted to type UserType.
Things I have tried:
serviceProvider.Setup(x => x.GetService())
.Returns(func);
serviceProvider.Setup(x => x.GetService(It.IsAny>))
.Returns(func);
Nothing seem to work.
ANSWER
Answered 2022-Feb-25 at 13:51Code smell aside, I would suggest using an actual IServiceProvider
to avoid having to arrange the behavior
class SomeClassTest{
Mock mockMale = new();
Mock mockFemale = new();
IServiceProvider serviceProvider;
[SetUp]
public void SetUp(){
mockMale.SetUp(x => x.GetAge()).Returns(20);
mockFemale .SetUp(x => x.GetAge()).Returns(50);
Func func = (type) => {
if (type == UserType.Male)
return mockMale.Object;
else return mockFemale.Object;
};
IServiceCollection services = new ServiceCollection();
services.AddSingleton(func);
serviceProvider = services.BuildServiceProvider();
}
[Test]
public void Test_MethodHello(){
new SomeClass(serviceProvider).MethodHello(UserType.Male);
}
}
QUESTION
I am upgrading my C#
function app from .net 3.1 to 6.0`.
When I run my test cases, I found that, 1 of my test case failed with the below error.
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: System.Net.HttpWebRequest. Could not find a parameterless constructor.
Basically, I am trying to mock HttpWebRequest and below is my piece of code for that.
var httpWebRequest = new Mock();
It is working fine in .Net 3.1. I am using Moq version 4.16.1 in both the projects.
ANSWER
Answered 2022-Feb-23 at 10:53Both HttpWebRequest constructors are obsolete and should not be used. You have to use the static function "Create" to create a new instance of the HttpWebRequest class:
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://www.contoso.com/");
To solve your issue, use the HttpClient class instead. This class has a parameterless constructor.
QUESTION
I am using automapper in my Program.cs like this:
builder.Services.AddAutoMapper(typeof(MappingProfiles));
And in my MappingProfiles I have configured this profile:
CreateMap()
.ForMember(d => d.ProductBrand, o => o.MapFrom(s => s.ProductBrand.Name))
.ForMember(d => d.ProductType, o => o.MapFrom(s => s.ProductType.Name))
.ForMember(d => d.PictureUrl, o => o.MapFrom());
Im my ProductUrlResolver I get IConfiguration injected in the constructor and that IConfiguration is used in the ProductUrlResolver to get some properties from appsettings.*.json
Now I would like to write a XUnit test for my controller where i use MOQ to mock out the services and also I do this to create my mapper that normally get injected into my controller:
var mapperConfiguration = new MapperConfiguration(cgf => cgf.AddProfile(new MappingProfiles()));
var mapper = new Mapper(mapperConfiguration);
But I get a error when the ProductUrlResolver is trying to get properties from the IConfiguration, and since I am not injecting the ProductUrlResolver into my MappingProfiles, but rather it is getting the ProductUrlResolver with the "o.MapFrom()" magic, then how do I trick the ProductUrlResolver to be able to get some data from some mocked or real configuration?
Thank you
Søren
ANSWER
Answered 2022-Feb-21 at 13:11How about this:
public class MappingProfiles: Profile
{
public MappingProfiles(IProductUrlResolver urlRes)
{
CreateMap()
.ForMember(d => d.ProductBrand, o => o.MapFrom(s => s.ProductBrand.Name))
.ForMember(d => d.ProductType, o => o.MapFrom(s => s.ProductType.Name))
.ForMember(d => d.PictureUrl, o => o.ConvertUsing(new MyConverter(urlRes));
}
private class MyConverter: IValueConverter { ... }
}
Now you can pass to the MappingProfiles either a normal or a mocked instance of your URL converter. If you want a normal instance, don't use the whole configuration in it, use Options pattern:
public class ProductUrlResolver : IProductUrlResolver {
void ProductUrlResolver(IOptions settings) { ... }
}
Than in your test you can instantiate it like this:
new ProductUrlResolver(Options.Create(new MySettings())
QUESTION
I have an Azure Function that has a blob trigger, in my function method args I expose the Blob itself via BlobClient and the name of the file uploaded.
[FunctionName("MyFunc")]
public async Task RunAsync([BlobTrigger("upload/{name}", Connection = "DataLake")]
BlobClient blob, string name)
{
var propertiesResponse = await blob.GetPropertiesAsync();
var properties = propertiesResponse.Value;
var metadata = properties.Metadata;
//do stuff with metadata
if (metadata.TryGetValue("activityId", out var activityId))
{
}
using (var stream = await blob.OpenReadAsync())
using (var sr = new StreamReader(stream))
{
//do some stuff with blob
}
}
I would like to unit test this function and was trying to mock BlobClient but having issues using the Moq library. I have found BlobsModelFactory that aims to help mocking but I can't see anything for BlobClient. Has anyone managed to mock BlobClient?
ANSWER
Answered 2022-Jan-08 at 14:32In line with the new Azure SDK guidelines public methods are marked virtual
so they can be mocked:
A service client is the main entry point for developers in an Azure SDK library. Because a client type implements most of the “live” logic that communicates with an Azure service, it’s important to be able to create an instance of a client that behaves as expected without making any network calls.
- Each of the Azure SDK clients follows mocking guidelines that allow their behavior to be overridden:
- Each client offers at least one protected constructor to allow inheritance for testing. All public client members are virtual to allow overriding.
In case of the BlobClient
mocking can be done like this*:
var mock = new Mock();
var responseMock = new Mock();
mock
.Setup(m => m.GetPropertiesAsync(null, CancellationToken.None).Result)
.Returns(Response.FromValue(new BlobProperties(), responseMock.Object))
Additional referencea:
- https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/README.md#mocking
- https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/samples/Mocking.md
*Code is for demonstration only, the references give clues on how to use BlobsModelFactory
QUESTION
I am trying to create a unit test using Moq which test Microsoft.AspNetCore.Identity user manager. I know that Moq is good for mocking interfaces, but UserManager does not have interface.
Here is my code:
Mock> userManagerMock = new Mock>();
// rest of my code ...
here is the error:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can not instantiate proxy of class: Microsoft.AspNetCore.Identity.UserManager`1[[WebAPI.Core.Model.User, Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].
Could not find a parameterless constructor.
ANSWER
Answered 2021-Dec-23 at 20:53You can mock classes with Moq
. You just need to create a new Mock
with valid constructor parameters. In your case:
var userManagerMock = new Mock>(Mock.Of>(), null, null, null, null, null, null, null, null);
When creating new mock for class, Moq uses one of the constructors of the class, in the UserManager
class, there is a single constructor with 9 parameters:
UserManager(IUserStore, IOptions, IPasswordHasher, IEnumerable>, IEnumerable>, ILookupNormalizer, IdentityErrorDescriber, IServiceProvider, ILogger>)
The only parameter that is mandatory is the first one, all the others you can pass null
value.
Now you can setup any virtual method or property.
Full example:
[TestMethod]
public void MockUserManager()
{
// Arrange
var userManagerMock = new Mock>(Mock.Of>(), null, null, null, null, null, null, null, null);
userManagerMock.Setup(x => x.CheckPasswordAsync(It.IsAny(), It.IsAny())).ReturnsAsync(true);
// Act
var res = userManagerMock.Object.CheckPasswordAsync(new User(), "123456").Result;
// Assert
Assert.IsTrue(res);
}
public class User
{
}
QUESTION
Interface:
Task> GetJSON(FileRequest request, FileItemsSerializer serializer = null, CsvConfiguration configuration = null, ClassMap mapper = null) where T: class, new();
Moq Setup:
Mock mock = new Mock();
mock.Setup(x => x.GetJSON(
It.IsAny(),
It.IsAny>(),
It.IsAny(),
It.IsAny>())
).Returns>((a) => {
return Task.FromResult(ServiceResponse.Create(
"Json Data",
"http://test.com/",
"Json Data",
"http://test.com/"));
});
Error message is
System.ArgumentException HResult=0x80070057 Message=Invalid callback. Setup on method with 4 parameter(s) cannot invoke callback with different number of parameters (1). Source=Moq StackTrace:
at Moq.MethodCall.<>c__DisplayClass22_0.g__ValidateCallback|4(Delegate callback) in C:\projects\moq4\src\Moq\MethodCall.cs:line 311 at Moq.MethodCall.SetReturnComputedValueBehavior(Delegate valueFactory) in C:\projects\moq4\src\Moq\MethodCall.cs:line 256 at Moq.Language.Flow.NonVoidSetupPhrase2.Returns[T1](Func
2 valueExpression) in C:\projects\moq4\src\Moq\Language\Flow\NonVoidSetupPhrase.cs:line 281
I would like to use
mock.Setup(x => x.GetJSON(It.IsAny())
).Returns>(
(a) => {
return Task.FromResult(ServiceResponse.Create(
"Json Data",
"http://test.com/",
"Json Data",
"http://test.com/"));
});
Since the last 3 parameters on getJSON are defaulted to null.
My question is: Why does not work and returns the error message. What am I doing wrong? I attempted to set it up similar to
Moq: Invalid callback. Setup on method with parameters cannot invoke callback with parameters
Thank you
ANSWER
Answered 2021-Dec-02 at 02:19Your code isn't working because you are using the Returns
overload that allows you to get hold of the parameters provided to the invocation, but you're not providing the type and you're not providing all of them. It's not about them having default values, it's that you're not providing the definition that Moq expects.
There's probably a few ways you can cut this. Given:
var adFileServiceMock = new Mock();
var expectedMockResponse = ServiceResponse.Create("Json Data", "http://test.com/", "Json Data", "http://test.com/");
- Always return that specific instance:
adFileServiceMock
.Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
.Returns(Task.FromResult(expectedMockResponse));
- Use a factory, (in this case I'm just returning the same instance everytime)
adFileServiceMock
.Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
.Returns(() => Task.FromResult(expectedMockResponse));
This is what I normally do.
- Specify the parameters
adFileServiceMock
.Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
.Returns((FileRequest providedFileRequest, object providedFileItemsSerializer, CsvConfiguration providedCsvConfiguration, object providedClassMap) => Task.FromResult(expectedMockResponse));
I do this when what I return depends on the values/objects provided to the invocation.
You've got to spec the types. I've been lazy here for brevity and used It.IsAnyType
and object
. I would normally use a specific type or a generic type parameter.
Finally given you're returning a task, at a guess you're using an async process so consider using ReturnsAsync
adFileServiceMock
.Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
.ReturnsAsync(() => expectedMockResponse);
Working LINQPad example:
async void Main()
{
var adFileServiceMock = new Mock();
var expectedMockResponse = ServiceResponse.Create("Json Data", "http://test.com/", "Json Data", "http://test.com/");
// adFileServiceMock
// .Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
// .Returns(Task.FromResult(expectedMockResponse));
//
// adFileServiceMock
// .Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
// .Returns(() => Task.FromResult(expectedMockResponse));
//
// adFileServiceMock
// .Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
// .Returns((FileRequest providedFileRequest, object providedFileItemsSerializer, CsvConfiguration providedCsvConfiguration, object providedClassMap) => Task.FromResult(expectedMockResponse));
adFileServiceMock
.Setup(x => x.GetJSON(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny>()))
.ReturnsAsync(() => expectedMockResponse);
var adFileService = adFileServiceMock.Object;
var mockResponse = await adFileService.GetJSON(new FileRequest(), new FileItemsSerializer(), new CsvConfiguration(), new ClassMap());
mockResponse.Should().BeSameAs(expectedMockResponse);
}
// You can define other methods, fields, classes and namespaces here
public interface IAdFileService
{
Task> GetJSON(FileRequest request, FileItemsSerializer serializer = null, CsvConfiguration configuration = null, ClassMap mapper = null) where T : class, new();
}
public class ServiceResponse
{
public static ServiceResponse Create(string a, string b, string c, string d)
{
return new ServiceResponse();
}
}
public class FileRequest { }
public class FileItemsSerializer { }
public class CsvConfiguration { }
public class ClassMap { }
public class Foo { }
Community Discussions, Code Snippets contain sources that include Stack Exchange Network
Vulnerabilities
No vulnerabilities reported
Install moq
Support
Find, review, and download reusable Libraries, Code Snippets, Cloud APIs from over 650 million Knowledge Items
Find more librariesExplore Kits - Develop, implement, customize Projects, Custom Functions and Applications with kandi kits
Save this library and start creating your kit
Share this Page