I'm using Autofixture for my unit tests, with auto-generated data.
To test a simple Controller endpoint (Get employee by Id), I'm doing something similar to this:
[Theory, AutoData]
public void GetEmployeeById_ValidId_ReturnsExpectedModel(
EmployeeModel expectedEmployee,
[Frozen] Mock<IEmployeeService> employeeServiceMock,
EmployeesController sut)
{
employeeServiceMock
.Setup(x => x.GetEmployeeById(42))
.Returns(expectedEmployee);
var actual = sut.GetEmployeeById(42);
actual.As<OkObjectResult>().Value.As<EmployeeModel>()
.Should().BeEquivalentTo(expectedEmployee);
}
And the controller:
[HttpGet("{id:int}")]
public IActionResult GetEmployeeById(int id)
{
var employee = employeeService.GetEmployeeById(id);
if (employee == null)
return NotFound("Employee not found");
return Ok(employee);
}
In this unit test, expectedEmployee is auto-generated with 'random' data. The sut (System Under Test) is configured to be generated with all its required dependencies (one of them is IEmplyeeService).
The problem with this unit test is that, if I change the employee before returning it from the controller, the test would still pass (because it's referencing the same object):
employee.SomeInternalModel.FooProperty = "Foo";
return Ok(employee);
So, I consider the above unit test to be bad.
To make the unit test fail in this scenario, I need to pass a separate object: deep copy of the EmployeeModel:
employeeServiceMock
.Setup(x => x.GetEmployeeById(42))
.Returns(expectedEmployee.DeepCopy());
I don't have time and resources to write deep copy methods for all my models.
How to easily auto-generate identical models? I thought about seed-ing the AutoFixture but it doesn't seem to support this feature.
Do you have any elegant suggestions?
I think you need to ask the question what are you testing? In your testcase you are only testing whether the SUT returns the employee returned by the service; IMO it doesn't matter whether it is the same instance. Updating a property shouldn't break this test.
You touch upon a wider problem though, in other cases you really want to compare your expected with an actual by structural equality in which case you could (using xUnits MemberData for instance) use a builder which generates two instances when you call it twice:
var employee = new EmployeeModelBuilder().Build();
Such a builder could be enhanced with With() methods:
var employee = new EmployeeModelBuilder().With(name: "John").Build();
Or you could just inline the creation of these objects using new EmployeeModel {}.
Structural equality means you need an object which overrides Equality members or use an IEqualityComparer<> in your asserts.
Update
If you do not want to use custom builders (like you say) you can instruct AutoFixture to generate objects with specific properties set with values. If you then ask it to create an instance twice (once for your expected and once for the instance returned by the service injected into your SUT) you can compare the expected with the actual in your Assert phase.
[Fact]
public void Sut_ReturnsEmployee_FromService()
{
var fixture = new Fixture();
fixture.Customize<EmployeeModel>(e => e.With(x => x.Name, "Foo"));
var expected = fixture.Create<EmployeeModel>();
var foundEmployee = fixture.Create<EmployeeModel>();
var employeeServiceMock = new Mock<IEmployeeService>();
employeeServiceMock.Setup(f => f.GetEmployeeById(42)).Returns(foundEmployee);
var sut = new EmployeeController(employeeServiceMock.Object);
var actual = sut.GetEmployeeById(42);
Assert.Equal(expected.Name, actual.Name);
}
Here I've used a [Fact] and the assertion compares two specific properties for equality, but when you compare structural equality you can just compare the objects themselves (like mentioned above).
Now you can verify that your SUT returns the expected instance without tampering and without using two references to the same instance.
Related
I have the following code where I'm trying to setup the mocked table based on the data type passed to the MockDbSet method.
private Mock<DbContext> mockContext = new Mock<DbContext>();
public DbContext GetContext()
{
return mockContext.Object;
}
public void MockDbSet<T>(params T[] sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
mockContext.Setup(c => c.Set(typeof(T))).Returns(dbSet.Object);
}
I get the following error at the mockContext.Setup line (22):
System.NotSupportedException: Conversion between generic and non-generic DbSet objects is not supported for test doubles.
I've tried
mockContext.Setup(c => c.Set<T>()).Returns(dbSet.Object);
This does not throw the exception, but also does not setup any data.
Is it possible to setup tables this way?
Thanks
To outline mocking at the Repository level:
Given Service / Controller code that interacts with a Repostory through a contract interface:
public interface IOrderRepository
{
IQueryable<Order> GetOrderById (int orderId);
IQueryable<Order> GetOrdersForCustomer (int customerId);
}
This is the preferred repository pattern I use. Returning IQueryable means that my consumers can take advantage of deferred execution to decide how the details will be used, resulting in more efficient queries. (I.e. using .Select() to get the fields they want, doing .Count() or .Any(), .FirstOrDefault(), or .Skip().Take() etc.)
alternatively you might use generic repositories:
public interface IRepository<Order>
{
Order GetOrderById (int orderId);
ICollection<Order> GetOrdersForCustomer (int customerId);
}
The repository methods would contain minimal to no business logic. In my case the repository would only be concerted with:
Authorization (retrieve data based on the current user / tenant)
Active / Soft-Delete state. (retrieve "active" data in a soft-delete environment unless told otherwise.)
Temporal state. (Retrieve "current" date unless told otherwise.)
All business logic should reside in your service classes or controllers, where it can be tested in isolation. To test the above 3 conditions (if applicable) I use integration tests. These conditions are very low-level checks and would not change on any regular basis.
Lets say the code under test is in a Controller.
public class OrderController : IOrderController
{
private readonly IOrderRepository _repository = null;
private readonly IUnitOfWorkFactory _uowFactory = null;
public OrderController(IUnitOfWorkFactory uowFactory, IOrderRepository repository)
{
if (uowFactory == null)
throw new ArgumentNullException("uowFactory");
if (repository == null)
throw new ArgumentNullException("repository");
_uowFactory = uowFactory;
_repository = repository;
}
public void SomeActionOnOrder(int orderId)
{
using (var unitOfWork = _uowFactory.Create())
{
var order = _repository.GetOrderById(orderId)
// Here lies your validation checks that the order was found,
// business logic to do your behaviour.. This is the stuff you want to test..
// ...
unitOfWork.Commit();
}
}
}
Now when you go to test your controller...
[Test]
public void EnsureSomeActionOnOrderDoesIt()
{
var uowMock = new Mock<IUnitOfWork>();
var uowFactoryMock = new Mock<IUnitOfWorkFactory>();
var repositoryMock = new Mock<IOrderRepository>();
var testOrderId = -1;
var stubOrders = new [] { newOrder { /* populate expected data... */ } };
uowMock.Setup(x=>x.Commit());
uowFactoryMock.Setup(x=>x.Create()).Returns(uowMock.Object);
repositoryMock.Setup(x=>x.GetOrderById(testOrderId)).Returns(stubOrders.AsQueryable());
var testController = new OrderController(uowFactoryMock.Object, repositoryMock.Object);
testController.SomeActionOnOrder(testOrderId);
// Everything "touched" as expected? (did the code fetch the object? did it save the changes?)
uowFactoryMock.VerifyAll();
uowMock.VerifyAll();
repositoryMock.VerifyAll();
// Perform asserts on your stub order if SomeAction modified state as you expected.
}
Integration tests against an actual database would handle any logic that the repositories would be expected to cover.
The repository pattern I have above is the IQueryable flavour, alternatively if you return an entity, just return the "stubs" with a stub order and return it.
The mocking framework I use is Moq. The above code may not be fully syntactically correct, based solely on memory. :)
The goal of unit tests, as far as TDD/BDD go, is that these tests should be reliably repeatable, and fast to execute so that they can be run repeatedly and frequently as you are developing. Keeping repositories relatively thin, and not touching on the business logic decisions means that they can serve as a reliable cut-off point for unit tests to mock out. The repository's job is to return data, so by mocking at that point it means we can control the data we expect the code under test to work with. We can mock it to return objects, null, throw exceptions, whatever our test scenario expects our code under test to handle.
In the above example I also demonstrate the use of a basic Unit of Work pattern which wraps the DB Context. The implementation that I use for EF is Medhime's DB Context Scope Factory/Locator. Using the Unit of Work pattern we also have mocks that can verify that the code under test is (or is not) saving data for instance. The repository would need to have a link to a unit of work (initialized in a constructor, or "located" as-per the Mehdime pattern) but we don't care about that aspect when testing our services & controllers, the repository is merely mocked out and its purpose is to return and (optionally) create data.
I'll have my repositories serve as factories for entities (I.e. CreateOrder() with list of product details & quantities) to ensure that new entities are initialized with all expected referential links and required data rather than relying on calling code. That calling code would have to be littered with extra queries etc. to retrieve referential data for a new order, so instead I have it pass the view model data through to the Order Repository to resolve, wire-up, and return a valid new Order entity.
In a recent project, I created an extension method of a List<T> (could be IEnumerable, or whatever).
public static Mock<DbSet<T>> MockList<T>(this List<T> list) where T: class
{
var mockDbSet = new Mock<DbSet<T>>();
var queryable = list.AsQueryable();
mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
return mockDbSet;
}
It is then quite simple to call.
var myData = new List<MyDataType> { new MyDataType(), new MyDataType(), ....};
var mockDb = new Mock<MyContext>();
mockDb.Setup(x => x.MyDatas).Returns(myData.MockList().Object);
I am quite new to Moq and I am not sure is this even possible, but let say, if I have one method named GeneratedHashedAndSaltedPassword()and I am making a call to that method from method named CheckUsersPassword() is there any chance that i can write from Unit test Moq expression that says: Verify if GeneratedHashedAndSaltedPassword is call from CheckUsersPassword method?
I will know that CheckUsersPassword method preformed correctly if it makes a call to GeneratedHashedAndSaltedPassword method without any exception.
What I have for now is not much, since I am having difficult time with Moq and it's logic.
[Test]
public void CheckIfPasswordIsHashed_Test()
{
var securityServiceMock = new Mock<User>();
securityServiceMock.Setup(m => m.CheckUsersPassword(It.IsAny<string>())).Returns(true);
securityServiceMock.VerifyAll();
}
I was trying to SetUp CheckUsersPassword, but I still don't know how or even if I can preform Verification I need. Does somebody has more experience with this kind of issue?
This is what CheckUserPassword does:
public bool CheckUsersPassword(string password)
{
return SecurityService.GenerateHashedAndSaltedPassword(password, Salt) == Password;
}
It makes simple call to GenerateHashedAndSaltedPassword() and compares result with current user password.
Important is to distinguish between code which is tested with unit test and external dependencies of this code. External dependencies are mocked with MOQ but tested code must be instantiated and called in the unit test directly.
In your question I assume you test the method CheckUsersPassword and that SecurityService is a dependency which should be mocked.
In the test you have to create instance of class (which contains the tested method) and pass mock of dependency to this tested class somehow.
[Test]
public void CheckIfPasswordIsHashed_Test()
{
// Arrange
// Mock dependency which is the service and setup
// GenerateHashedAndSaltedPassword so it does what you need
var securityServiceMock = new Mock<User>();
securityServiceMock.Setup(m => m.GenerateHashedAndSaltedPassword(
It.IsAny<string>(),
ItIsAny<Salt>())
.Returns(Password);
// TestedClass needs a place where the mocked instance can be injected,
// e.g. in constructor, or public property
var testedClass = new TestedClass(securityServiceMock.Object);
// Act
testedClass.CheckUsersPassword(password);
// Assert
securityServiceMock.Verify(m => m.GenerateHashedAndSaltedPassword(
It.IsAny<string>(),
ItIsAny<Salt>()),
Times.Once());
}
I am trying to mock (using Moq) a class set a return object on a class that only exposes two properties.
In my limited Moq experience I would normally use a Setup() lamda to define the method call and then Returns() to spit back the desired output.
What I am falling down on here is the Setup(). There isn't a "method" to call as the constructor does the work, populates the two properties and then returns.
My class that I want to mock...obviously dummied down:
public class CarResponse
{
public IMetaModel meta { get; set; }
public List<ICarModel> cars { get; set; }
public CarResponse(Common.Models.Car car)
{
this.cars = new List<ICarModel>();
}
}
My feeble attempt at mocking:
private Mock<CarResponse> _carResponse = new Mock<CarResponse>(MockBehavior.Strict);
_carResponse.Setup( ????? ).Returns(new CarResponse() { meta = new MetaModelV2(), cars = foo });
To further clarify...here is the code I am trying to write a unit test for:
public HttpResponseMessage AddPickup()
{
//....code removed for brevity....
//this repository is mocked and returns the object exactly as I want it
var car = carRepository.GetCar(carId);
if (!errorInfo.Any()) //This check is bogus it never gets sets
{
RequestHelper rqh = new RequestHelper();
response = rqh.CreateResponse(Request, HttpStatusCode.OK, new CarResponse(car));
}
My unit test:
[TestMethod]
public void AddValidPickupCorrectResponse()
{
//arrange
//...lots of code here left off for setting up http context etc
//act---
var response = controller.AddPickup();
//assert
}
If I were to use a precanned object as suggested how would I "hook" it to the code under test. For example I write a unit test that uses my pre-canned object instead of a Moq but how do I get that pre-canned object to be used by the SUT?
There are few problems which can get in the way of properly unit testing the above code:
new-ing up the response helper
new-ing up the CarResponseObject
In essence, unless a class in real POCO (i.e. only data with public setters and getters), using "new" is a killer for unit testing. I.e. it is not a unit test (test the unit/method in isolation). It tests the behavior of the CarResponse ctor, as well as the working of RequestHelper.
Consider the following changes:
Inject the RequestHelper (so you can mock the CreateResponse method)
Use and inject some mapping factory of sort, which can create CarResponseObjects from Car.
Consider CarResponse to implement something like IResponse, so your RequestHelper, or factory, can return interfaces.
With all of the above, your test will look like (pseudo code, not complete):
//arrange
//....
var carInDB = new Car();
_repoMock.Setup(...).Returns(car);
var carResponse = Mock.Of<IResponse>();
_mapperMock.Setup(m=>m.CreateResponse(car).Returns(carResponse);
var responseFromHelper = new WhateverResponseIsNeeded(); //(or create a new mock IResponse - note! new mock, different than car response
_helperMock.Setup(_controller.Request, HttpStatusCode.OK, carResponse).Returns(responseFromHelper);
//act
var response = _controller.AddPickup();
//assert
response.Should().Be.SameInstanceAs(responseFromHelper)
You can use SetupGet and SetupSet to mock properties. However, I don't think you can mock concrete classes.
If you are dealing with a value type you might find it easier to not bother mocking and just used a pre-canned object.
I have a web service, which I would like to do some unit testing on, however I am not sure how I can do this. Can anyone give any suggestions? Below is the webservice, it produces an object with three fields, but only when there is values in the database queue.
[WebMethod]
public CommandMessages GetDataLINQ()
{
CommandMessages result;
using (var dc = new TestProjectLinqSQLDataContext())
{
var command = dc.usp_dequeueTestProject();
result = command.Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return result;
}
}
You don't need to consume your data over the WebService to Unit test it. You can just create another project in your solution with a reference to your WebService project and call directly the methods.
First up, what you've posted can't really be Unit Tested at all; by definition, a Unit Test can have only a single reason to fail; However in your case, a single test of GetDataLINQ() (the "System Under Test" or "SUT") could fail because of a problem with any of the dependencies in the function - namely, TestProjectLinqSQLDataContext and usp_dequeueTestProject.
When you call this method from a Unit test, these dependencies at present are probably beyond your control because you didn't directly create them - they are most likely created in your page classes' constructor. (Note: this is an assumption on my part, and I could be wrong)
Also, because these dependencies are at present real "live" objects, which have hard dependencies on an actual database being present, it means your tests aren't able to run independently, which is another requirement for a Unit Test.
(I'll assume your page's class file is "MyPageClass" from now on, and I will pretend it's not a web page code-behind or asmx code-behind; because as other posters have pointed out, this only matters in the context of accessing the code via HTTP which we're not doing here)
var sut = new MyPageClass(); //sut now contains a DataContext over which the Test Method has no control.
var result = sut.GetDataLINQ(); //who know what might happen?
Consider some possible reasons for failure in this method when you call sut.GetDataLINQ():
new TestProjectLinqSQLDataContext() results in an exception because of a fault in TestProjectLinqSQLDataContext's constructor
dc.usp_dequeueTestProject() results in an exception because the database connection fails, or because the stored procedure has changed, or doesn't exist.
command.Select(...) results in an exception because of some as of yet unknown defect in the CommandMessage constructor
Probably many more reasons (i.e failure to perform correctly as opposed to an exception being thrown)
Because of the multiple ways to fail, you can't quickly and reliably tell what went wrong (certainly your test runner will indicate what type of exception threw, but that requires you to at least read the stack trace - you shouldn't need to do this for a Unit Test)
So, in order to do this you need to be able to setup your SUT - in this case, the GetDataLINQ function - such that any and all dependencies are fully under the control of the test method.
So if you really want to Unit Test this, you'll have to make some adjustments to your code. I'll outline the ideal scenario and then one alternative (of many) if you can't for whatever reason implement this. No error checking included in the code below, nor is it compiled so please forgive any typos, etc.
Ideal scenario
Abstract the dependencies, and inject them into the constructor.
Note that this ideal scenario will require you to introduce an IOC framework (Ninject, AutoFAC, Unity, Windsor, etc) into your project. It also requires a Mocking framework (Moq, etc).
1. Create an interface IDataRepository, which contains a method DequeueTestProject
public interface IDataRepository
{
public CommandMessages DequeueTestProject();
}
2. Declare IDataRepository as a dependency of MyPageClass
public class MyPageClass
{
readonly IDataRepository _repository;
public MyPageClass(IDataRepository repository)
{
_repository=repository;
}
}
3. Create an actual implementation of IDataRepository, which will be used in "real life" but not in your Unit Tests
public class RealDataRepository: IDataRepository
{
readonly MyProjectDataContext _dc;
public RealDataRepository()
{
_dc = new MyProjectDataContext(); //or however you do it.
}
public CommandMessages DequeueTestProject()
{
var command = dc.usp_dequeueTestProject();
result = command.Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return result;
}
}
This is where you will need to involve your IOC framework such that it can inject the correct IDataRepository (i.e RealDataRepository) whenever your MyPageClass is instantiated by the ASP.NET framework
4. Recode your GetDataLINQ() method to use the _repository member
public CommandMessages GetDataLINQ()
{
CommandMessages result;
return _repository.DequeueTestProject();
}
So what has this bought us? Well, consider now how you can test against the following specification for GetDataLINQ:
Must always invoke DequeueTestProject
Must return NULL if there is no data in the database
Must return a valid CommandMessages instance if there is data in the database.
Test 1 - Must always invoke DequeueTestProject
public void GetDataLINQ_AlwaysInvokesDequeueTestProject()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to just return null; we don't care about the return value for now
repo.Setup(r=>r.DequeueTestProject()).Returns(null);
//create the SUT, passing in the fake repository
var sut = new MyPageClass(repo.Object);
//call the method
sut.GetDataLINQ();
//Verify that repo.DequeueTestProject() was indeed called.
repo.Verify(r=>r.DequeueTestProject(),Times.Once);
}
Test 2 - Must return NULL if there is no data in the database
public void GetDataLINQ_ReturnsNULLIfDatabaseEmpty()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to return null;
repo.Setup(r=>r.DequeueTestProject()).Returns(null);
var sut = new MyPageClass(repo.Object);
//call the method but store the result this time:
var actual = sut.GetDataLINQ();
//Verify that the result is indeed NULL:
Assert.IsNull(actual);
}
Test 3 - Must return a valid CommandMessages instance if there is data in the database.
public void GetDataLINQ_ReturnsNCommandMessagesIfDatabaseNotEmpty()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to return null;
repo.Setup(r=>r.DequeueTestProject()).Returns(new CommandMessages("fake","fake","fake");
var sut = new MyPageClass(repo.Object);
//call the method but store the result this time:
var actual = sut.GetDataLINQ();
//Verify that the result is indeed NULL:
Assert.IsNotNull(actual);
}
Because we can Mock the IDataRepository interface, therfore we can completely control how it behaves.
We could even make it throw an exception, if we needed to test how GetDataLINQ responds to unforseen results.
This is the real benefit of abstracting your dependencies when it comes to Unit Testing (not to mention, it reduces coupling in your system because dependencies are not tied to a particular concrete type).
Not Quite ideal method
Introducing an IOC framework into your project may be a non-runner, so here is one alternative which is a compromise. There are other ways as well, this is just the first that sprang to mind.
Create the IDataRepository interface
Create the RealDataRepository class
Create other implementations of IDataRepository, which mimic the behaviour we created on the fly in the previous example. These are called stubs, and basically they are just classes with a single, predefined behaviour that never changes. This makes then ideal for testing, because you always know what will happen when you invoke them.
public class FakeEmptyDatabaseRepository:IDataRepository
{
public CommandMessages DequeueTestProject(){CallCount++;return null;}
//CallCount tracks if the method was invoked.
public int CallCount{get;private set;}
}
public class FakeFilledDatabaseRepository:IDataRepository
{
public CommandMessages DequeueTestProject(){CallCount++;return new CommandMessages("","","");}
public int CallCount{get;private set;}
}
Now modify the MyPageClass as per the first method, except do not declare IDataRepository on the constructor, instead do this:
public class MyPageClass
{
private IDataRepository _repository; //not read-only
public MyPageClass()
{
_repository = new RealDataRepository();
}
//here is the compromise; this method also returns the original repository so you can restore it if for some reason you need to during a test method.
public IDataRepository SetTestRepo(IDataRepository testRepo)
{
_repository = testRepo;
}
}
And finally, modify your unit tests to use FakeEmptyDatabaseRepository or FakeFilledDatabaseRepository as appropriate:
public void GetDataLINQ_AlwaysInvokesDequeueTestProject()
{
//create a fake implementation of IDataRepository
var repo = new FakeFilledDatabaseRepository();
var sut = new MyPageClass();
//stick in the stub:
sut.SetTestRepo(repo);
//call the method
sut.GetDataLINQ();
//Verify that repo.DequeueTestProject() was indeed called.
var expected=1;
Assert.AreEqual(expected,repo.CallCount);
}
Note that this second scenario is not an ivory-tower-ideal scenario and doesn't lead to strictly pure Unit tests (i.e if there were a defect in FakeEmptyDatabaseRepository your test could also fail) but it's a pretty good compromise; however if possible strive to achieve the first scenario as it leads to all kinds of other benefits and gets you one step closer to truly SOLID code.
Hope that helps.
I would change your Code as follows:
public class MyRepository
{
public CommandMessage DeQueueTestProject()
{
using (var dc = new TestProjectLinqSQLDataContext())
{
var results = dc.usp_dequeueTestProject().Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return results;
}
}
}
Then code your Web Method as:
[WebMethod]
public CommandMessages GetDataLINQ()
{
MyRepository db = new MyRepository();
return db.DeQueueTestProject();
}
Then Code your Unit Test:
[Test]
public void Test_MyRepository_DeQueueTestProject()
{
// Add your unit test using MyRepository
var r = new MyRepository();
var commandMessage = r.DeQueueTestProject();
Assert.AreEqual(commandMessage, new CommandMessage("What you want to compare"));
}
This allows your code to be reusable and is a common design pattern to have Data Repositories. You can now use your Repository Library everywhere you need it and test it in only one place and it should be good everywhere you use it. This way you don't have to worry about complicated tests calling WCF Services. This is a good way of testing Web Methods.
This is just a short explanation and can be improved much more, but this gets you in the right direction in building your Web Services.
We find ourselves coding repetitive fixture/mock setups in many test-cases - like this case:
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var encodingMock = fixture.Freeze<Mock<IEncodingWrapper>>();
var httpClientMock = fixture.Freeze<Mock<IHttpWebClientWrapper>>();
var httpResponseMock = fixture.Freeze<Mock<IHttpWebResponseWrapper>>();
var httpHeaderMock = fixture.Freeze<Mock<IHttpHeaderCollectionWrapper>>();
var etag = fixture.CreateAnonymous<string>();
byte[] data = fixture.CreateAnonymous<byte[]>();
Stream stream = new MemoryStream(data);
encodingMock.Setup(m => m.GetBytes(It.IsAny<string>())).Returns(data);
httpHeaderMock.SetupGet(m => m[It.IsAny<string>()]).Returns(etag).Verifiable();
httpClientMock.Setup(m => m.GetResponse()).Returns(httpResponseMock.Object);
httpResponseMock.Setup(m => m.StatusCode).Returns(HttpStatusCode.OK);
httpResponseMock.SetupGet(m => m.Headers).Returns(httpHeaderMock.Object);
httpResponseMock.Setup(m => m.GetResponseStream()).Returns(stream);
As per the idea that the tests should be self-contained and readable from start to end we dont use magical Setup/Teardown methods.
Can we in any way (AutoFixture customizations, helper methods) reduce the "grunt work" of these tests?
From Growing Object-Oriented Software (GOOS) comes a piece of good advice: if a test is hard to write, it's feedback about the API of the System Under Test (SUT). Consider redesigning the SUT. In this particular example, it looks as though the SUT has at least four dependencies, which might indicate a violation of the Single Responsibility Principle. Would it be possible to refactor to Facade Services?
Another great piece of advice from GOOS is that
Mocks should only be used for Commands
Stubs should be used for Queries
In the above example it looks as though you need to do a lot of Moq Setup for methods that are really Queries. That indicates a test smell as well. Is there a Law of Demeter violation somewhere? Would it be possible to cut the method chain?
You can create a composite Customization that will customize the fixture by using all contained customizations.
public class HttpMocksCustomization : CompositeCustomization
{
public HttpMocksCustomization()
: base(
new AutoMoqCustomization(),
new HttpWebClientWrapperMockCustomization(),
new HttpWebResponseWrapperMockCustomization()
// ...
)
{
}
}
Each customization can be defined as follow:
public class HttpWebClientWrapperMockCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var mock = new Mock<IHttpWebClientWrapper>();
mock.Setup(m => m.GetResponse()).Returns(httpResponseMock.Object);
fixture.Inject(mock);
}
}
public class HttpWebResponseWrapperMockCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
var mock = new Mock<IHttpWebResponseWrapper>();
mock.Setup(m => m.StatusCode).Returns(HttpStatusCode.OK);
fixture.Inject(mock);
}
}
// The rest of the Customizations.
Then inside the test method you can do this:
var fixture = new Fixture().Customize(new HttpMocksCustomization());
That way, when you request a Mock instance you don't have to repeat the setup steps. The one we customized earlier will be returned:
var httpClientMock = fixture.Freeze<Mock<IHttpWebClientWrapper>>();
However, if you use xUnit.net, things can be simplified even further.
You can create an AutoDataAttribute-derived type to provide auto-generated data specimens generated by AutoFixture as an extention to xUnit.net's Theory attribute:
public class AutoHttpMocksDataAttribute : AutoDataAttribute
{
public AutoHttpMocksDataAttribute()
: base(new Fixture().Customize(new HttpMocksCustomization()))
{
}
}
Then, in your test method you can pass the Mocks as arguments:
[Theory, AutoHttpMocksData]
public void MyTestMethod([Freeze]Mock<IHttpWebClientWrapper> httpClientMock, [Freeze]Mock<IHttpWebResponseWrapper> httpResponseMock)
{
// ...
}
If all of your tests use this code, it should be placed in the set up/tear down methods. It's ok if your set up/tear down methods are somewhat complicated, as long as all of your unit tests are depending on it. This is certainly better than duplicating all that complicated stuff in every test. When I read a test, I know that setup and teardown are part of each test implicitly, so I don't think you lose anything in readability either. The thing to avoid is including things in setup that not every test needs. This creates confusing situations where you setup method doesn't match all your tests nicely. Ideally your set up method should apply 100% to every single test.
If the shared code is not used in all your tests, extract the shared code into helper functions.Writing good tests code is just like writing any other good code, and the same principles apply.