I have the following setup:
A calendar controller that calls a calendar service that calls a calendar client wrapper that calls the client. Controller -> Service -> ClientWrapper -> Client.
I am making an integration test that mocks the lowest tier (the client) and calls the controller to see if the client was called correctly.
My CalendarControllerBuilder:
internal class CalendarControllerBuilder
{
public CalendarControllerBuilder()
{
CalendarClientMock = new Mock<ICalendarServiceClient>(MockBehavior.Strict);
}
public Mock<ICalendarServiceClient> CalendarClientMock { get; set; }
public CalendarControllerBuilder With(Mock<ICalendarServiceClient> calendarClientWrapperMock)
{
CalendarClientMock = calendarClientWrapperMock;
return this;
}
public CalendarController Create()
{
var calendarClientWrapperMock = new CalendarClientWrapper(CalendarClientMock.Object);
var calenderService = new CalendarService(calendarClientWrapperMock);
return new CalendarController(calenderService);
}
}
Test setup with customization registration:
internal class CalenderControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Register<CalendarController>(() =>
{
// ----- ICalendarServiceClient mock setups -----
var calendarServiceClientMock = new Mock<ICalendarServiceClient>(MockBehavior.Strict);
calendarServiceClientMock.Setup(m => m.GetEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(fixture.Create<EventList>()).Verifiable();
return new CalendarControllerBuilder()
.With(calendarServiceClientMock)
.Create();
});
}
}
My automoq data attribute (using AutoFixture.Xunit2):
public class Attributes
{
public class AutoMoqDataAttribute<T> : AutoDataAttribute where T : ICustomization, new()
{
public AutoMoqDataAttribute()
: base(() => new Fixture()
.Customize(
new CompositeCustomization(
new AutoMoqCustomization(),
new T())))
{
}
}
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() => new Fixture()
.Customize(
new AutoMoqCustomization()))
{
}
}
}
My test that works fine and uses the customization registration:
[Theory]
[AutoMoqData<CalenderControllerCustomization>]
public async Task Test_GetAllEvents_ClientIsCalledCorrectlyAndReturnsCorrectData(
IFixture fixture,
[Frozen] Mock<ICalendarServiceClient> calendarServiceClientMock,
CalendarController sut)
{
// Arrange
var startDate = fixture.Create<DateTimeOffset>();
var endDate = fixture.Create<DateTimeOffset>();
// Act
var eventList = await sut.GetAllEvents(startDate, endDate);
// Assert
eventList.Events.Count.Should().Be(3); // fixture always create 3 of lists here
calendarServiceClientMock.Verify();
}
THE PROBLEM:
Now I want to override the setup with my own data returned.
[Theory]
[AutoMoqData<CalenderControllerCustomization>]
public async Task Test_GetAllEvents_ClientIsCalledCorrectlyAndReturnsCorrectData_Overridden(
IFixture fixture,
[Frozen] Mock<ICalendarServiceClient> calendarServiceClientMock,
CalendarController sut)
{
// Arrange
var startDate = fixture.Create<DateTimeOffset>();
var endDate = fixture.Create<DateTimeOffset>();
var result = fixture.Build<EventList>()
.With(x => x.Events, fixture.CreateMany<Event>(5).ToList())
.Create();
// override client mock setup:
calendarServiceClientMock.Setup(m => m.GetEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(fixture.Build<EventList>()
.With(x => x.Events, fixture.CreateMany<Event>(5).ToList())
.Create()).Verifiable();
// Act
var eventList = await sut.GetAllEvents(startDate, endDate);
// Assert
eventList.Events.Count.Should().Be(5); // FAILS - IT GETS 3 AND NOT 5
calendarServiceClientMock.Verify(); // THIS FAILS TOO IF I SET 3 IN ABOVE
}
I have tried with and without the Frozen attribute.
What am I missing here? I don't want to call my calendarcontroller builder as the point is to avoid boilerplate. Do I need a registration of the client or something else I'm missing
(maybe related to Override Autofixture customization setup but using moq and not n-subtitute. Could not get this to work even with correct order of parameters)
Thanks for reading!
With the current way you customize the fixture I don't think you can. By creating a custom builder and instantiating the mock by hand you've basically painted yourself in a corner.
To get AutoFixture to control the instances you need in the test, you must allow it to generate them. Here's a possible solution.
The root of your SUT is the controller. Let's say it receives as a parameter an ICalendarService that's always the concrete implementation CalendarService.
To tell AutoFixture that the implementation is always a concrete type you can relay the resolved type to the concrete implementation.
fixture.Customizations.Add(new TypeRelay(typeof(ICalendarService), typeof(CalendarService)));
Next the service takes as a constructor parameter an abstraction that's ICalendarClient which is resolved as the wrapper but only for the service. This means you have to identify the constructor parameter and relay the request to the wrapper type.
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedRequestRelay(typeof(CalendarClientWrapper)),
new YourConstructorParameterSpecification()));
The YourConstructorParameterSpecification is a IRequestSpecification implementation that identifies a request as a parameter of type ICalendarClient that belongs to the constructor of type CalendarService.
FixedRequestRelay is a simple ISpecimenBuilder that always resolves the same predefined request from ISpecimenContext instead of the received one.
Here's a very basic implementation of it.
public record FixedRequestRelay(object Request) : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
=> context.Resolve(this.Request);
}
Next you have your wrapper that also takes as a parameter an abstraction of type ICustomerClient. However this instance you want to be resolved as a mock that you can control from the test. Since you use AutoFixure.AutoMoq you can leave this one as is and let AutoMoq generate a mock for it.
Let's say this is the resulting customization.
public class CalendarCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new TypeRelay(typeof(ICalendarService), typeof(CalendarService)));
fixture.Customizations.Add(new FilteringSpecimenBuilder(
new FixedRequestRelay(typeof(CalendarClientWrapper)),
new AndRequestSpecification(
new ParameterSpecification(typeof(ICalendarClient), "client"),
new ParameterMemberSpecification(
new DeclaringTypeSpecification(
new ExactTypeSpecification(typeof(CalendarService)))))));
}
}
By using it you can write a test like this.
[Theory, MyData]
public async Task Foo(
[MinLength(5)] Event[] events,
[Frozen] Mock<ICalendarClient> clientMock,
CalendarController controller,
DateTime start, DateTime end)
{
clientMock
.Setup(x => x.GetAllEvents(It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(events);
var actual = await controller.GetAllEvents(start, end, default);
Assert.Equal(events, actual);
}
Related
I have a code like this (I have to test a repo, you'll see the code below)
public class SomeClass
{
public AsyncPolicyWrap PropName { get; }
public SomeClass(...)
{
PropName = Policy.WrapAsync(someRetry,someCircuitBreaker)
// here there are passed some methods that return someRetry - AsyncRetryPolicy
// and someCircuitBreaker - AsyncCircuitBreakerPolicy
}
}
then I have another repo class
public class SomeRepo : ISomeRepo
{
private readonly AsyncPolicy _somePolicy;
public SomeRepo(..., SomeClass someClass) : base(...)
{
_somePolicy = someClass.PropName;
}
public async Task<Result<SomeDTO>> GetDTO(Guid someId)
{
var someResponse = await _somePolicy.ExecuteAsync(() =>
HttpClient.GetAsync(serviceName, $"endpointUrl"));
...
}
}
2 pieces of code above can't be changed cause they are in prod and I as a junior dev just have to cover code with tests if possible
I have tried to write a test like this
[TestMethod]
public async Task DoStuff()
{
var repository = DefaultSome();
var result = await repository.GetDTO(new Guid());
result.ShouldNotBeNull(); // don't pay attention I'll change stuff which has to be asserted
}
private SomeRepo DefaultSome(Some some = null)
{
some = some ?? A.Fake<ISome>();
/// HERE I TRIED TO MOCK STUFF IN DIFFERENT WAYS AND I HAVE AN ERROR
var policyWrap = A.Dummy<AsyncPolicyWrap>();
//var test = Policy.WrapAsync(A.Fake<AsyncRetryPolicy>(), A.Fake<AsyncCircuitBreakerPolicy>());
//var test = Policy.WrapAsync(A.Fake<IAsyncPolicy>(), A.Fake<IAsyncPolicy>());
A.CallTo(() =>
policyWrap.ExecuteAsync(A<Func<Task<HttpResponseMessage>>>._))
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
var policy = A.Fake<RetryPolicies>();
A.CallTo(() =>
policy.PropName)
.Returns(policyWrap);
return new SomeRepo(some, ..., policy);
}
here is an error i get
I get similar for commented // var test = ... variats
Concrete vs Abstract
Whenever you need to mock something then rely on abstraction rather than concrete implementation.
AsyncPolicyWrap is a concrete class not an abstract like AsyncPolicy
Also as the exception says this class does not have a public parameterless constructor.
It has an internal ctor with 2 parameters:
internal AsyncPolicyWrap(AsyncPolicy outer, IAsyncPolicy inner)
: base(outer.ExceptionPredicates)
{
_outer = outer;
_inner = inner;
}
So, you should prefer AsyncPolicy abstract class or IAsyncPolicy interface.
With or without result
Please be aware that in Polly each Policy has two versions:
One which does not return any result
One which does return some result
Based on the SomeRepo's code your Policy should return an HttpResponseMessage.
So, you should use IAsyncPolicy<HttpResponseMessage> or AsyncPolicy<HttpResponseMessage> to indicate that your policy will return an HttpResponseMessage.
Mocking
Whenever you mock an IAsyncPolicy<HttpResponseMessage> then you don't have to recreate the combined policy (like you did in the comments). All you have to do is to define how should the ExecuteAsync behave.
Happy path:
var mockedPolicy = new Mock<IAsyncPolicy<HttpResponseMessage>>();
mockedPolicy
.Setup(policy => policy.ExecuteAsync(It.IsAny<Func<Task<HttpResponseMessage>>>()))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));
Unhappy path:
var mockedPolicy = new Mock<IAsyncPolicy<HttpResponseMessage>>();
mockedPolicy
.Setup(policy => policy.ExecuteAsync(It.IsAny<Func<Task<HttpResponseMessage>>>()))
.ThrowsAsync(new HttpRequestException("Something bad happened"));
I've used moq to mock the policy but the same concept can be applied for FakeItEasy.
My WEB API project is using a Generic Repository that implements an interface like this:
public interface IGenericEFRepository<TEntity> where TEntity : class
{
Task<IEnumerable<TEntity>> Get();
Task<TEntity> Get(int id);
}
public class GenericEFRepository<TEntity> : IGenericEFRepository<TEntity>
where TEntity : class
{
private SqlDbContext _db;
public GenericEFRepository(SqlDbContext db)
{
_db = db;
}
public async Task<IEnumerable<TEntity>> Get()
{
return await Task.FromResult(_db.Set<TEntity>());
}
public async Task<TEntity> Get(int id)
{
var entity = await Task.FromResult(_db.Set<TEntity>().Find(new object[] { id }));
if (entity != null && includeRelatedEntities)
{
//Some Code
}
return entity;
}
}
Well now I want to test this service. for this I have used the following code:
public class CustomerControllerTest
{
CustomerController _controller;
ICustomerProvider _provider;
ICustomerInquiryMockRepository _repo;
public CustomerControllerTest()
{
_repo = new CustomerInquiryMockRepository();
_provider = new CustomerProvider(_repo);
_controller = new CustomerController(_provider);
}
[Fact]
public async Task Get_WhenCalled_ReturnsOkResult()
{
// Act
var okResult = await _controller.Get();
// Assert
Assert.IsType<OkObjectResult>(okResult);
}
[Fact]
public async Task GetById_UnknownCustomerIdPassed_ReturnsNotFoundResult()
{
// Act
var notFoundResult = await _controller.Get(4);
// Assert
Assert.IsType<NotFoundResult>(notFoundResult);
}
}
Which my tests are working fine by creating a fake non-generic service manually with mock data (In-Memory) like below, instead of using my real generic interface and it's implementation that uses my database as data-source:
public interface ICustomerInquiryMockRepository
{
Task<IEnumerable<CustomerDTO>> GetCustomers();
Task<CustomerDTO> GetCustomer(int customerId);
}
And it's implementation:
public class CustomerInquiryMockRepository : ICustomerInquiryMockRepository
{
public async Task<IEnumerable<CustomerDTO>> GetCustomers()
{
return await Task.FromResult(MockData.Current.Customers);
}
public async Task<CustomerDTO> GetCustomer(int CustomerId)
{
var Customer = await Task.FromResult(MockData.Current.Customers.FirstOrDefault(p => p.CustomerID.Equals(CustomerId)));
if (includeTransactions && Customer != null)
{
Customer.Transactions = MockData.Current.Transactions.Where(b => b.CustomerId.Equals(CustomerId)).ToList();
}
return Customer;
}
}
And the MockData.Current.Customers is just a simple fake (In-Memory) List of Customers. Long story short, the above tests are working fine, however I am feeling I have repeated my self a lot and so I have decided to use Moq library instead of creating fake service manually. For this purpose I have used Moq like this:
public class CustomerControllerTest
{
CustomerController _controller;
ICustomerProvider _provider;
//ICustomerInquiryMockRepository _repo;
Mock<ICustomerInquiryMockRepository> mockUserRepo;
public CustomerControllerTest()
{
mockUserRepo = new Mock<ICustomerInquiryMockRepository>();
//_repo = new CustomerInquiryMockRepository();
_provider = new CustomerProvider(mockUserRepo.Object);
_controller = new CustomerController(_provider);
}
[Fact]
public async Task Get_WhenCalled_ReturnsOkResult()
{
mockUserRepo.Setup(m => m.GetCustomers())
.Returns(Task.FromResult(MockData.Current.Customers.AsEnumerable()));
// Act
var okResult = await _controller.Get();
// Assert
Assert.IsType<OkObjectResult>(okResult);
}
[Fact]
public async Task GetById_UnknownCustomerIdPassed_ReturnsNotFoundResult()
{
//Arrange
I don't know how can I use Moq here and in the other parts of my tests
// Act
var notFoundResult = await _controller.Get(4);
// Assert
Assert.IsType<NotFoundResult>(notFoundResult);
}
Now my question is the Mock is working fine when I use it for Mocking the GetCustomers method because I simply paste the code from GetCustomers method in the CustomerInquiryMockRepository in the Returns method of the Mock object. However I don't really have any idea how can I use Mock for my other methods inside this Repository. Should I replace anything that I have in the Return method?
You can mock out your repository like so:
var mockUserRepo = new Mock<ICustomerInquiryMockRepository>();
mockUserRepo.Setup(x => x.GetCustomers())
.Returns(Task.FromResult(MockData.Current.Customers.AsEnumerable());
mockUserRepo.Setup(x => x.GetCustomer(It.IsAny<int>()))
.Returns(res => Task.FromResult(MockData.Current.Customers.ElementAt(res));
If you want to mock out specific values for GetCustomer, you can do:
mockUserRepo.Setup(x => x.GetCustomer(It.Is<int>(y => y == 4)))
.Returns(res => Task.FromResult(/* error value here */));
I think the key here is to use It.Is or It.IsAny based on how you want to mock out the object. Generally, you also want to mock out interfaces that are used in production code, instead of having production code depend on something with Mock or Test in the name. I would recommend against taking a production code dependency on something named ICustomerInquiryMockRepository, if that is indeed what you're doing and not just part of the MCVE you've provided.
Tests usually use mocking to test the workflow of an application at a high level, so you would usually want to mock out your services level, call a controller, and verify that the services were called as expected. For example:
// Production class sample
class ProductionController
{
public ProductionController(IService1 service1, IService2 service2) { }
public void ControllerMethod()
{
var service1Result = service1.Method();
service2.Method(service1Result);
}
}
// Test sample
// arrange
var expectedResult = new Service1Result();
var service1 = Mock.Of<IService1>(x => x.Method() == expectedResult);
var service2 = Mock.Of<IService2>(x => x.Method(It.Is<Service1Result>(y => y == expectedResult)));
var controller = new ProductionController(service1, service2);
// act
controller.ControllerMethod();
// assert
Mock.Get(service1).Verify(x => x.Method(), Times.Once);
Mock.Get(service2).Verify(x => x.Method(expectedResult), Times.Once);
As you can see from the example, you aren't checking the business logic of either of the services, you're just validating that the methods were called with the expected data. The test is built around verification of methods being called, not any particular branching logic.
Also, unrelated to your question, Moq also has a cool syntax you can use for simple mock setups:
var repo = Mock.Of<ICustomerInquiryMockRepository>(x =>
x.GetCustomers() == Task.FromResult(MockData.Current.Customers.AsEnumerable()));
You can use Mock.Get(repo) if you need to do additional setup on the repository. It's definitely worth checking out, I find it much nicer to read.
I'm trying to generate some subclasses of ApiController (WebAPI 2) using AutoFixture (3.50.6).
I customized AF to allow generating ApiControllers using this customization.
Because of further customization needs, I'd like to create a SpecimenBuilder that would create any type of ApiController and apply this configuration with a simple
fixture.Create<DummyController>();
I tried this test (NUnit 3) :
[TestFixture]
public class ApiControllerSpecimenBuilderTests
{
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization());
fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
}
public class ApiControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Inject(new UriScheme("http"));
fixture.Customize<HttpConfiguration>(c => c
.OmitAutoProperties());
fixture.Customize<HttpRequestMessage>(c => c
.Do(x =>
x.Properties.Add(
HttpPropertyKeys.HttpConfigurationKey,
fixture.Create<HttpConfiguration>())));
fixture.Customize<HttpRequestContext>(c => c
.Without(x => x.ClientCertificate));
}
}
public class ApiControllerSpecimenBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var t = request as Type;
if (t == null || !typeof(ApiController).IsAssignableFrom(t))
{
return new NoSpecimen();
}
var controller = context.Resolve(t) as ApiController;
// ...
return controller;
}
}
public class DummyController : ApiController
{
}
That fails with the following error :
Ploeh.AutoFixture.ObjectCreationException : AutoFixture was unable to
create an instance of type System.RuntimeType because the traversed
object graph contains a circular reference. [...]
Path: Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController
--> Foo.Common.Tests.AutoFixture.SpecimenBuilders.DummyController
Why does the DummyController have a reference to its own type ?
Moreover, if I change the test with an empty customization for DummyController, it passes :
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization())
.Customize(new DummyControllerCustomization()); // new customization
fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
public class DummyControllerCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<DummyController>(c => c);
}
}
In this case, the SpecimenBuilder seems to not be hit anymore with the DummyController type. What does this empty customization do that makes the test pass ? Does it override the specimen builder ? But then why doesn't it throw the same exception, as I don't tell him to omit anything (and anyway, I wouldn't know what to make it omit...) ?
I guess I could use the OmitOnRecursionBehavior, but I'd like to keep the default behavior to avoid recursions in all the other cases, plus I'd rather understand what is happening (or if I did smth really stupid).
Just remove ApiControllerSpecimenBuilder:
[TestFixture]
public class ApiControllerSpecimenBuilderTests
{
[Test]
public void ShouldCreateAControllerUsingSpecimenBuilder()
{
var fixture = new Fixture()
.Customize(new AutoMoqCustomization())
.Customize(new ApiControllerCustomization());
//fixture.Customizations.Add(new ApiControllerSpecimenBuilder());
var ctl = fixture.Create<DummyController>();
}
}
The above version of your test passes (on my machine).
The problem is that ApiControllerSpecimenBuilder enters into an infinite recursion if it passes the initial Guard Clause:
var controller = context.Resolve(t) as ApiController;
The call to context.Resolve(t) enters a new object creation 'session'. AutoFixture asks each ISpecimenBuilder in its tree whether they can handle a request for t. When it reaches ApiControllerSpecimenBuilder, it responds by calling context.Resolve(t) again, and so on ad infinitum.
You don't need to do any of that work yourself, as AutoFixture is already perfectly capable of creating ApiController instances for you (as long as the ApiControllerCustomization is in place).
If I understand the overall use case correctly, however, the actual requirement is that you'd like to do some sort of post-processing on the ApiController instances, after AutoFixture has created the object for you.
The general solution to such a scenario is to use Postprocessor or Postprocessor<T>, but that can sometimes be a bit involved to get right. Often, there are simpler ways to achieve what you want to do.
If you need help with that, please ask another question. You don't need to put up a bounty next time, as I normally monitor the autofixture tag. This question somehow escaped my attention; sorry about that!
I have the following (simplified) code.
public class Controller
{
private readonly IService _service;
public Controller(IService service)
{
_service = service;
}
public async Task<IHttpActionResult> Create(MyObject object)
{
var result = _service.method(object);
if (!result.Succeeded)
{
return this.GetErrorResult(object);
}
}
}
and SimpleInjector is used to inject the dependency between _service and its implementation class, like this:
public static void Register(Container container)
{
container.Register<IService, Service>();
}
As a note, injection and unit testing are new to me so I do not fully understand them, but am learning.
If I run the application through Swagger, all is working fine.
As a note, the Register function is called when I run the application through Swagger.
Now, I am trying to setup some unit tests using NUnit, and am Mocking the IService object like this:
var Service = new Mock<IService>();
Controller _controller = new Controller(Service.Object);
_controller.Create(new MyObject object());
which seems to be correct to me so far - although I am not sure?
The problem is that for the unit test, result is always null - I think the is because there is a problem with my Mock of the interface - it does not seem to be finding the method - it never steps into it and does not show up int he debugger.
As a note, for the unit test, the Register method does not get called. I did try calling it to register the dependency, but it does not help.
As I said above, this is all new to me and I am on the edge of my understanding on all of this.
I am out of ideas and do not know where to look from here, so any help would be greatly appreciated.
EDIT:
The original question had the following:
public async Task<IHttpActionResult> Create(string content)
which I have updated to:
public async Task<IHttpActionResult> Create(MyObject object)
Can anyone advise how I can pass in a generic reference to MyObject on the setup, without having to make an instance of this class.
So basically I want to tell it that an instance of this class will be passed in, without creating that instance.
I have tried the following:
Service.Setup(x => x.method(It.IsAny<MyObject>())
but it says cannot convert MethodGroup to MyObject
and here is the definition of IService:
public interface IService
{
IdentityResult method(ApplicationUser user, UserLoginInfo login);
}
You need to configure the Mock object to return something for IService.method as follows:
var Service = new Mock<IService>();
Service.Setup(x => x.method(It.IsAny<string>())
.Returns<string>(str => **whatever result you need**);
With the addition of your actual IService definition, you should change the Setup call to:
Service.Setup(x => x.method(It.IsAny<ApplicationUser>(), It.IsAny<UserLoginInfo>())
.Returns<ApplicationUser, UserLoginInfo>((user, login) => new IdentityResult(true));
The setup method has to be called on the Mock object.
var Service = new Mock<IService>();
Service.Setup(x=>x.method("argument")).Returns(YourReturnObject)
Controller _controller = new Controller(Service.Object);
Using your simplified example
public class Controller
{
private readonly IService _service;
public Controller(IService service)
{
_service = service;
}
public async Task<IHttpActionResult> Create(string content)
{
var result = await _service.method(content);
if (!result.Succeeded)
{
return this.GetErrorResult(result);
}
return Ok();
}
}
Lets assume IService is defined as
public interface IService {
Task<Result> method(string input);
}
public class Result {
public bool Succeeded { get; set; }
}
For the unit test you need to setup the mock to fake the actions wanted for the test
public async Task Controller_Given_Content_Should_Return_Ok() {
//Arrange
var input = "content";
var mockService = new Mock<IService>();
mockService
.Setup(m => m.method(input))
.ReturnAsync(new Result { Succeeded = true });
var _controller = new Controller(mockService.Object);
//Act
var result = await _controller.Create(input);
//Assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result,typeof(OkResult));
}
Given that the method under test is asynchronous you would want to setup the test to be asynchronous as well.
I have read Mark Seeman's article on auto-mocking and I'm now writing a re-usable windsor container based on that article.
My implementation of Mark's article (basically copied directly)
The main work is done in the AutoMoqResolver class. This will provide a mock whenever a class has a dependency on an interface:
public class AutoMoqResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public AutoMoqResolver(IKernel kernel)
{
this.kernel = kernel;
}
public bool CanResolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
return dependency.TargetType.IsInterface;
}
public object Resolve(
CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
var mockType = typeof(Mock<>).MakeGenericType(dependency.TargetType);
return ((Mock)this.kernel.Resolve(mockType)).Object;
}
}
The AutoMoqResolver is added to the container using the following implementation of the IWindsorInstaller interface:
public class AutoMockInstaller<T> : IWindsorInstaller
{
public void Install(
IWindsorContainer container,
IConfigurationStore store)
{
container.Kernel.Resolver.AddSubResolver(
new AutoMoqResolver(container.Kernel));
container.Register(Component.For(typeof(Mock<>)));
container.Register(Classes
.FromAssemblyContaining<T>()
.Pick()
.WithServiceSelf()
.LifestyleTransient());
}
}
Then my container simply runs the installer and it is ready to automatically provide mocks for any interface dependencies in unit tests:
public class AutoMockContainer<T> : WindsorContainer
{
public AutoMockContainer()
{
// simply run the auto-mock installer
this.Install(new AutoMockInstaller<T>());
}
}
Super!
I've tested this and my dependencies are happily mocked automatically so I then went to apply it to some real code. This is when I realised that the solution doesn't help me because of the pattern I tend to follow when testing a class. My specific issue is that I want to be able to auto-mock the SUT itself in order to verify that one method on the SUT is called from another.
My code that needs to be tested
I'll explain myself by way of an example. I am developing MVC code and I am supporting unobtrusive AJAX using the following general pattern:
public Class ExampleController : Controller
{
private IService service;
public ExampleController(IService service)
{
this.service = service;
}
public PartialViewResult DoSomethingWithAjax()
{
this.PerformTask();
return this.PartialView();
}
public RedirectToRouteResult DoSomethingWithoutAjax()
{
this.PerformTask();
return this.RedirectToAction("SomeAction");
}
protected virtual void PerformTask()
{
// do something here
}
}
My test pattern
So in order to verify that the PerformTask() method was called from DoSomethingWithAjax() or DoSomethingWithoutAjax(), I define a new TestableExampleController class like this:
public class TestableExampleController : ExampleController
{
public TestableExampleController(IService service) : base(service)
{
}
public virtual void PerfomTaskPublic()
{
base.PerfomTask();
}
protected override void PerformTask()
{
this.PerformTaskPublic();
}
}
I can then use TestableExampleController as my SUT so the following test will pass:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a mock TestableExampleController
var controllerMock = new Mock<TestableExampleController>();
controllerMock.CallBase = true;
// use the mock controller as the SUT
var sut = controllerMock.Object;
//// Act
sut.DoSomethingAjax();
//// Assert
controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
My problem
Refactoring this test to use my AutoMockContainer class like this doesn't work:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a container
var container = new AutoMockContainer<TestableExampleController>();
// resolve a mock SUT using the container
var controllerMock = container.Resolve<Mock<TestableExampleController>>();
controllerMock .CallBase = true;
// use the mock controller as the SUT
var sut = controllerMock.Object;
//// Act
sut.DoSomethingAjax();
//// Assert
controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
The test fails to create an instance of Mock<TestableExampleController> because it can't find a parameterless constructor.
Can not instantiate proxy of class: MyNamespace.TestableExampleController.
Could not find a parameterless constructor.
Parameter name: constructorArguments
My proposed solution
Ideally I would like to implement a wrapper class which can be registered with the container to automatically provide a mock for any component:
public class ComponentWrapper<T> where T : class
{
public ComponentWrapper(Mock<T> componentMock)
{
componentMock.CallBase = true;
this.ComponentMock = componentMock;
}
public Mock<T> ComponentMock { get; private set; }
public T Component
{
get { return this.ComponentMock.Object; }
}
}
I would like to be able to write the following test that passes:
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a container
var container = new AutoMockContainer<TestableExampleController>();
// resolve a ComponentWrapper using the container
var wrapper = container.Resolve<ComponentWrapper<TestableExampleController>>();
//// Act
// call a method using the component
wrapper.Component.DoSomethingAjax();
//// Assert
// verify a method call using the mock
wrapper.ComponentMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
I can't quite get my head round how to achieve this and I've spent most of the day fiddling with new ISubDependencyResolver implementations but I just can't get this to work.
Hopefully my question is clear and the answer is actually relatively simple?
It turns out that AutoFixture.AutoMoq will do exactly what I want out of the box so thank you to TrueWill for pointing me in the right direction.
The following simple test will pass:
[TestMethod]
public void Run_Calls_DoSomethingProtected()
{
//// Arrange
// AutoMoqCustomization allows AutoFixture to
// be used an an auto-mocking container
var fixture = new Fixture().Customize(new AutoMoqCustomization());
// simply ask the fixture to create a mock
var sutMock = fixture.Create<Mock<TestableDummySystem>>();
//// Act
// exercise the mock object
sutMock.Object.Run();
//// Assert
// this verification passes!
sutMock.Verify(x => x.DoSomethingProtectedPublic());
}