I started to use moq but from my understanding I always have to mock up all the methods that could be called even if I really do not care about them.
Sometimes it takes so long to mockup stuff you forget what you want to do. So I been looking at auto mocking but I am not sure what one I should use.
AutoFixture as an auto-mocking container
Automocking
I don't get how to use the first one at all. I sort of get the second one but never really tried it.
I am not sure if one is better than the other. The only thing I know is I am using AutoFixtures already what is a dependency of the first one.
So maybe in the long run it makes sense to go with the first one but like I said I can't find any basic tutorials on how to use it.
Edit
I am trying to follow "Nikos Baxevanis" examples but I am running into errors.
Failure: System.ArgumentException : A matching constructor for the given arguments was not found on the mocked type.
----> System.MissingMethodException : Constructor on type 'DatabaseProxyded46c36c8524889972231ef23659a72' not found.
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var fooMock = fixture.Freeze<Mock<IFoo>>();
// fooMock.Setup(x => x.GetAccounts(It.IsAny<IUnitOfWork>()));
var sut = fixture.CreateAnonymous<AdminService>();
sut.Apply();
fooMock.VerifyAll();
I think it is because of my petapoco unitOfWork property
PetaPoco.Database Db { get; }
Not sure if I got to mock this up somehow or what.
While I have never used moq-contrib Automocking, I could probably provide some information on using AutoFixture as an auto-mocking container.
Currently there is support for Moq, Rhino Mocks, FakeItEasy, and NSubstitute. Just install the appropriate extension AutoMoq, AutoRhinoMocks, AutoFakeItEasy, and AutoNSubstitute.
Once you have installed one of the extensions for Auto Mocking the extra call is:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
(or if you are using Rhino Mocks)
var fixture = new Fixture()
.Customize(new AutoRhinoMockCustomization());
(or if you are using FakeItEasy)
var fixture = new Fixture()
.Customize(new AutoFakeItEasyCustomization());
(or if you are using NSubstitute)
var fixture = new Fixture()
.Customize(new AutoNSubstituteCustomization());
Example 1
public class MyController : IController
{
public MyController(IFoo foo)
{
}
}
public interface IFoo
{
}
Here is how to use AutoFixture to create instances of MyController class:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var sut = fixture.CreateAnonymous<MyController>();
Now, if you inspect the sut variable you will see the the IFoo is a mocked instance (having a type name similar to Castle.Proxies.IFooProxy).
Example 2
This examples extends the previous one.
You can instruct AutoFixture to use your own, pre-configured, mocked instance:
var fooMock = fixture.Freeze<Mock<IFoo>>();
// At this point you may setup expectation(s) on the fooMock.
var sut = fixture.CreateAnonymous<MyController>();
// This instance now uses the already created fooMock.
// Verify any expectation(s).
That's basically it - but it can go further!
Below are the previous examples using AutoFixture decleratively with the xUnit.net extension.
Example 1
[Theory, AutoMoqData]
public void TestMethod(MyController sut)
{
// Start using the sut instance directly.
}
Example 2
[Theory, AutoMoqData]
public void TestMethod([Frozen]Mock<IFoo> fooMock, MyController sut)
{
// At this point you may setup expectation(s) on the fooMock.
// The sut instance now uses the already created fooMock.
// Verify any expectation(s).
}
You may find more information on this blog post which contains links to everything related around AutoFixture, xUnit.net, and Auto Mocking.
Hope that helps.
Related
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.
I am quite new to .NET Core. How can I define a DI container within the NUnit class library project?
I know that it is done through IServiceCollection, but since there isn't any Startup method, I don't know where to get the instance implementing this interface.
Also I would like to be able to load definitions from other class libraries (being the subject of testing). That should be simpler as I can just create a static method in that class library with one parameter that is IServiceCollection, but again, how do I get it?
A side question is: I presume some of the interfaces could be mocked for the purpose of tests, but how can I replace a mapping already created using of of IServiceCollection's methods like AddSingleton or AddTransient?
There is a Remove method, but it is not documented.
IServiceCollection is implemented by the ServiceCollecion class. So if you want to do this for integration tests then you can use the ServiceCollection class to create your own ServiceProvider.
var services = new ServiceCollection();
services.AddTransient<IMyInterface, MyClass>();
services.AddScoped<IMyScopedInteface, MyScopedClass>();
...
var serviceProvider = sc.BuildServiceProvider();
You can now use the serviceProvider instance in your tests to get your classes:
var myClass = serviceProvider.GetService<IMyInterface>();
If you want to mock some of the interfaces instead of using the real ones then, instead of adding the real class/interface into the service collection you can add a mock instead:
mockInterface = new Mock<IMyInterface>();
sc.AddScoped<IMyInterface>(factory => mockInterface.Object);
Generally you don't want to create a DI container for your tests but, as you realise, you want to mock them instead. So, for example, if this is a class you want to test:
public class UserService
{
private readonly IUserDatabase _userDatabase;
public UserService(IUserDatabase userDatabase)
{
_userDatabase = userDatabase;
}
public bool DoesUserExist(int userId)
{
return _userDatabase.UserExists(userId);
}
}
And this is the definition of the interface used:
public interface IUserDatabase
{
bool UserExists(int userId);
}
In our tests we can mock the interface to return a specific value we want for our test:
[TestClass]
public class UserServiceTests
{
[TestMethod]
public void DoesUserExist_ForValidUserId_ReturnsTrue()
{
var fakeUserId = 123;
var mockUserDatabase = new Mock<IUserDatabase>();
mockUserDatabase.Setup(udb => udb.UserExists(fakeUserId)).Returns(true);
var userService = new UserService(mockUserDatabase.Object);
var result = userService.DoesUserExist(fakeUserId);
Assert.IsTrue(result);
mockUserDatabase.VerifyAll();
}
}
So in this test we have used Moq to create a mock of our interface. We don't need to use a DI container because we are in controller of creating the class we are testing. The DI container is of more use in production as it enables the application to create any dependencies it needs without your code having to call new - which is a big problem if you are trying to unit test your classes.
The .VerifyAll() method checks that any methods set up on the mock object, in this case we setup a call to UserExists, was actually called.
There are plenty of examples of how to use Moq and mocking interfaces in general. A quickstart guide to Moq is here.
In my ViewModel, portions of functionality are enabled/disabled depending on the logged-in individual's permissions. The ViewModel relies on a dependency-injected ISecurity object to check if a user has a specific permission. Different portions of functionality require different permissions.
public Interface ISecurity
{
bool UserHasPermision(int userId, string permission);
}
In my production code, the concrete implementation of ISecurity interacts with an external application which does not allow me to change an individual's permissions. I created a FakeSecurity class that would allow me to do this in unit tests.
class FakeSecurity: ISecurity
{
private Dictionary<int, List<string>> permissions = new Dictionary<int, List<string>>();
public bool UserHasPermission(int userId, string permission)
{
return permissions.ContainsKey(userId) &&
permissions[userId].Contains(permission);
}
//Not defined in ISecurity
public void SetPermission(int userId, string permission, bool hasPermission)
{
if (!permissions.ContainsKey(userId))
{
permissions[userId] = new List<string>();
}
List<string> userPermissions = permissions[userId];
if (hasPermission)
{
userPermissions.Add(permission);
}
else
{
userPermissions.Remove(permission);
}
}
}
The problem here is that SetPermission() is not defined in the ISecurity interface, so in order for my Unit Tests to set an individual's permissions I need to cast the ISecurity object registered with my IUnityContainer to a FakeSecurity object. I am told that my unit test should be ignorant of the specific type of implementation that is being used for a particular interface and that calling methods that are not defined in the interface is an anti-pattern.
[TestMethod]
public void UserDoesNotHavePermission()
{
// test setup
IUnityContainer iocContainer = GetIocContainer();
ISecurity sec = iocContainer.Resolve<ISecurity>(); //registered singleton
(sec as FakeSecurity).SetPermission(GetCurrentUser().Id, "Save Colors", false);
var viewModel = iocContainer.Resolve<MaintainColorsViewModel>(); //per-request
// asserts
Assert.IsFalse(viewModel.CanSave);
}
[TestMethod]
public void UserHasPermission()
{
// test setup
IUnityContainer iocContainer = GetIocContainer();
ISecurity sec = iocContainer.Resolve<ISecurity>(); //registered singleton
(sec as FakeSecurity).SetPermission(GetCurrentUser().Id, "Save Colors", true);
var viewModel = iocContainer.Resolve<MaintainColorsViewModel>(); //per-request
// asserts
Assert.IsTrue(viewModel.CanSave);
}
Is this a bad practice or not? I realize that I shouldn't cast my ISecurity instace to a particular type within my application code, but is this really an issue Unit Tests?
I am told that my unit test should be ignorant of the specific type of implementation
This is incorrect. It is completely normal and good practice to let tests use both fake implementations and the class under test directly.
You however, are using the DI container in your unit tests, and that actually is bad practice. Although the use of the DI container is okay when you're writing integration tests (since you want to test components in integration with other components), using the DI library in unit tests leads to hard to read and maintain tests. With unit tests, you test code in isolation. This means that you usually create the class under test by hand, and inject the required fake dependencies to get the test running.
I would therefore expect such unit test to look like this:
public void CanSave_CurrentUserHasNoPermission_ReturnsFalse() {
// Arrange
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
var viewModel = new MaintainColorsViewModel(noPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsFalse(actualResult);
}
public void CanSave_CurrentUserHasPermission_ReturnsTrue() {
// Arrange
var hasPermission = new FakeSecurity { CurrentUserHasPermission = true };
var viewModel = new MaintainColorsViewModel(hasPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsTrue(actualResult);
}
public void CanSave_Always_QueriesTheSecurityForTheSaveColorsPermission() {
// Arrange
var security = new FakeSecurity();
var viewModel = new MaintainColorsViewModel(security);
// Act
bool temp = viewModel.CanSave;
// Assert
Assert.IsTrue(security.RequestedPermissions.Contains("Save Colors"));
}
There are a few things to note about this code:
Both the FakeSecurity and the MaintainColorsViewModel are created directly in the tests here; no DI library is used. This makes the tests much more readable and maintainable (and faster).
I considerably simplified the FakeSecurity class (shown below), because you want fake classes to be as simple as possible.
A third test is added to check explicitly whether the MaintainColorsViewModel requests the expected permission.
The AAA pattern (Arrange/Act/Assert) is implemented explicitly.
To allow these tests to be written the way they are, the following change has been made to the ISecurity abstraction:
interface ISecurity
{
bool UserHasPermission(string permission);
}
The userId parameter has been removed from the UserHasPermission method. The reason for this is that the ISecurity implementation will be able to find out who the current user is by itself. Allowing consumers of ISecurity to pass this parameter along only means that the API is getting more complex, there is more code to write, there's a bigger chance of programming errors, and we therefore need more supporting tests. In other words, the sole addition of this userId property forces a lot of extra production and test code to write and maintain.
Here is the simpflified FakeSecurity class:
class FakeSecurity : ISecurity
{
public bool CurrentUserHasPermission;
public List<string> RequestedPermissions = new List<string>();
public bool UserHasPermission(string permission)
{
this.RequestedPermissions.Add(permission);
return this.CurrentUserHasPermission;
}
}
The FakeSecurity class now has very little code and that makes it, just by looking at it, very easy to check for correctness. Remember, test code should be as simple as possible. Side note: replacing this class with a generated mock object, doesn't make our code easier. In most cases it will actually make our unit tests harder to read, understand and maintain.
One reason for developers to start using a DI container inside their unit tests is because the manual creation of the class under test (with all its fake dependencies) causes maintenance issues in their tests. This is true actually; if the MaintainColorsViewModel has multiple dependencies, and we would create that MaintainColorsViewModel in each test, the addition of a single dependency would cause us to change all our MaintainColorsViewModel tests. This often is a reason for developers to either use a DI container -or- revert to mocking frameworks.
This however is not a good reason to start using a DI container or mocking library. A simple refactoring can completely remove the maintenance problem; we just have to create a factory method as follows:
private static MaintainColorsViewModel CreateViewModel(params object[] dependencies) {
return new MaintainColorsViewModel(
dependencies.OfType<ISecurity>().SingleOrDefault() ?? new FakeSecurity(),
dependencies.OfType<ILogger>().SingleOrDefault() ?? new FakeLogger(),
dependencies.OfType<ITimeProvider>().SingleOrDefault() ?? new FakeTimeProvider(),
dependencies.OfType<IUserContext>().SingleOrDefault() ?? new FakeUserContext());
}
Here I assume that the MaintainColorsViewModel contains 4 dependencies (namely ISecurity, ILogger, ITimeProvider and IUserContext). The CreateViewModel factory method allows passing in all dependencies using a params array, and the method tries to get each abstraction from the array and when missing replaces it with the default fake implementation.
With this factory, we can now rewrite our tests to the following:
[TestMethod]
public void CanSave_CurrentUserHasNoPermission_ReturnsFalse()
{
// Arrange
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
MaintainColorsViewModel viewModel = CreateViewModel(noPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsFalse(actualResult);
}
Or we can pass in multiple dependencies if the test requires this:
[TestMethod]
public void CanSave_CurrentUserHasNoPermission_LogsWarning()
{
// Arrange
var logger = new FakeLogger();
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
MaintainColorsViewModel viewModel = CreateViewModel(logger, noPermission);
// Act
bool temp = viewModel.CanSave;
// Assert
Assert.IsTrue(logger.Entries.Any());
}
Do note that this test is just here for educational purposes. I don't suggest the view model to actually do the logging; that should not be its responsibility.
The moral of the story here is actually that good design can simplify your testing efforts considerably to the point that you can write less code and less tests, while improving the quality of your software.
You shouldn't use a DI container in unit tests, see the answer in this question.
In unit tests, the object graph that you are testing is usually small (usually a single class). So you don't need a DI container.
Without a container, here is how your test would look like:
//Arrange
FakeSecurity fake_security = new FakeSecurity();
fake_security.SetPermission(GetCurrentUser().Id, "Save Colors", false);
MaintainColorsViewModel sut = new MaintainColorsViewModel(fake_security);
//Act
...
Please note that I am assuming that you are using constructor injection to inject ISecurity into MaintainColorsViewModel.
Please note that instead of creating a FakeSecurity class, you can use auto-generated mocks by using mocking frameworks. Here is a link to one of the mocking frameworks called FakeItEasy.
Based on my experience, when you feel something not natural in Unit Test, you may want to re-factor your code.
According to this code, there are a couple choices.
Define the permission dictionary as a property in the interface. So it is easy to set values at unit testing.
Define a permission layer, IPermission, to add/retrieve/remove permission. Then you can mock IPermission in unit testing your Security implementation.
At least I would define the SetPermission method in ISecurity, your current code does not let you define an ISecurity object and let you set permission. Think the following code.
{
ISecurity sec = CreateSecurity()
sec.SetPermission() // ERROR, SetPermission is not a method in ISecurity.
}
private ISecurity CreateSecurity()
{
return new Security()
}
However, I am not sure how to unit test in this case on top of my head.
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.