xUnit Mock request new instance from IoC container - c#

I am writing some unit tests for a method that uploads a file using SSH.Net.
The project is a WPF app and uses Caliburn.Micro as MVVM framework and also to inject the following object in the constructor of the class I am testing:
private IFileTransferManager _fileTransferManager;
public FileUploadViewModel(IFileTransferManager fileTransferManager) : base(eventAggregator)
{
_fileTransferManager = fileTransferManager;
}
In the test project I am mocking IFileTransferManager:
private Mock<IFileTransferManager> _fileTransferManager = new Mock<IFileTransferManager>();
But now I got to the point, when in code I need to ask for a new instance of IFileTransferManager from IoC container, IoC being a static class in Caliburn.Micro:
_fileTransferManager = IoC.Get<IFileTransferManager>();
await _fileTransferManager.UploadFile(connection, file.FullName, destinationPath).ConfigureAwait(false);
How can I refactor the above code to make it testable, because currently it throws System.InvalidOperationException in Caliburn.Micro.dll due to the fact that I am re-instantiating _fileTransferManager?

I would probably do something like this, assuming there are other limiting factors that mean you want to change as little outward detail about the class as possible (note: I haven't tested this so may have to tweak a little)
public class ClassIAmTesting
{
//Have a Func to fetch a file manager...
private Func<IFileTransferManager> _filemgr = null;
//Have a property which we'll use in this class to get the File manager
public Func<IFilterTransferManager> GetFileManager
{
get
{
//If we try to use this property for the first time and it's not set,
//then set it to the default implementation.
if (_fileMgr == null)
{
_fileMgr = () => IoC.Get<IFileTransferManager>();
}
return _fileMgr;
}
set
{
//allow setting of the function which returns an IFileTransferManager
if (_fileMgr == null)
{
_fileMgr = value;
}
}
}
//this is the method you ultimately want to test...
public async Task<bool> SomeMethodIAmTesting()
{
//don't do this any more:
//_fileTransferManager = IoC.Get<IFileTransferManager>();
//instead do this.
_fileTransferManager = GetFileManager();
await _fileTransferManager
.UploadFile(connection, file.FullName, destinationPath)
.ConfigureAwait(false);
return true;
}
}
Then in your testing:
Mock<IFileTransferManager> _fileTransferManager = new Mock<IFileTransferManager>();
var cut = new ClassIAmTesting();
//not used Moq for a long time, but think you have to access .Object to get to the
//actual implementation of IFileTransferManager?
cut.GetFileManager = () => _fileTransferManager.Object;
//Do actual tests..
var result = cut.SomeMethodIAmTesting();
//Do assertions...
I suggest this approach because:
It provides a way of overriding the way the class gets the IFileTransferManager for testing
It 'falls back' to the default implementation if this override is not used, preserving the original behaviour - you don't need to change existing calls to this class at all from non-testing code
It does not change the Constructor or add a new one, which I assume is a problem since you don't simply inject an instance of the IFileTransferManager in.
one improvement might be to make the set internal which would prevent other projects from setting this method, and it could then be exposed via InternalVisibleTo or similar, but I'm trying to keep the scope fairly tight...

Inject a factory using a Func<TResult> delegate.
private readonly Func<IFileTransferManager> fileTransferManagerFactory;
public FileUploadViewModel(Func<IFileTransferManager> fileTransferManagerFactory) : base(eventAggregator) {
this.fileTransferManagerFactory = fileTransferManagerFactory;
}
This would allow for as many instances as needed being created when uploading
//get an instance using factory delegate
var fileTransferManager = fileTransferManagerFactory();
await fileTransferManager.UploadFile(connection, file.FullName, destinationPath).ConfigureAwait(false); IoC.Get<IFileTransferManager>();
For unit testing a function can be easily created to provid as many mocks needed for the test case

Related

unit test for a method that takes an instance through Resolve<T> of Autofac

I'm facing a problem trying to implement a unit test for a method on a service.
The architecture of the project is a little bit cumbersome, to say the less...
The problem is that within the method to test it calls another method to take an instance of another service, here is the little monster:
public void SendOrderEmail(string orderCode)
{
Order order= GetOrderService().SerachByCode(orderCode);
.... Send email with the order ....
}
private IOrderService GetOrderService()
{
return OrderService = AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
}
Please, don't ask why a service calls another service or why is that service not injected at the constructor, as i said the architecture of this project is weird in some points.
I just need to know what is the way to implement a unit test for a method like that.
Thank you!
I would refactor a little the code, let the class that implement this method have IOrderService injected through the constructor, save the instance and then use it,
this way you can inject your fake IOrderService during the test (or use Automock) :)
If you really really can't change the constructor, you can use a property to set IOrderService
---------------- edit
Since i got some downvote on this answer I've tried to get to understand better what is going on.
I'm not sure about this, but seems like you can't edit this class you wrote about, you just want to test it.
Well if that is the case i think i can still give you some advices.
Advice number one: make a test project, link the class file, make a new file with a class like the following one.
class AutofacDependencyResolver {
public static Current { get; private set; }
public ILifetimeScope ApplicationContainer { get; private set; }
public AutofacDependencyResolver(ILifetimeScope scope) {
Current = this;
ApplicationContainer = scope;
}
}
Since the class you need to test is linked it's gonne to compile it and you just can now achieve what you need.
The other (and i think better) advice is do not test stuff you did not wrote / can't modify. What i'm suggesting is writing an adapter, so a class that use the one you can't modify as a black box.
In this case i think you need to test the email, so just check the email output the address stuff like that and ignore the rest.
the people who wrote those classes should have followed solid principles...
As others have said, and you're probably aware yourself anyway, you really want to refactor classes like this and use constructor injection if at all possible. Service location is generally considered an anti-pattern (https://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/) and it specifically makes unit testing like this harder and less transparent.
However, if you absolutely can't refactor, you can still make methods like this somewhat testable by just providing different registrations for the services you're accessing via service location.
In your case, if you have:
public class EmailSender
{
public void SendOrderEmail(string orderCode)
{
Order order = GetOrderService().SearchByCode(orderCode);
//....Send email with the order ....
}
private IOrderService GetOrderService()
{
return AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
}
}
...and you're looking to specifically run unit tests over SendOrderEmail to validate the logic surrounding your IOrderService implementation (which could be easily covered by a separate test), the other classes implied there might look like:
public class AutofacDependencyResolver // this is problematic but we can't change it
{
public AutofacDependencyResolver(IContainer applicationContainer)
{
ApplicationContainer = applicationContainer;
}
public IContainer ApplicationContainer { get; }
public static AutofacDependencyResolver Current { get; private set; }
public static void SetContainer(IContainer container)
{
Current = new AutofacDependencyResolver(container);
}
}
public static class ContainerProvider // this sets up production config across your app
{
public static IContainer GetProductionContainer()
{
var builder = new ContainerBuilder();
builder.RegisterType<RealOrderService>()
.As<IOrderService>();
// register all other real dependencies here
return builder.Build();
}
}
With that setup, you only need to provide mocks which are required for the specific method you're testing, assuming you can set your container within AutofacDependencyResolver easily in order to have production and test configuration running in parallel. That might look like the following, using xUnit, Moq and Autofac in a test project:
public class EmailSenderTests
{
private readonly Mock<IOrderService> _orderService;
public EmailSenderTests()
{
// to set up the test fixture we'll create a mock OrderService and store a reference to the mock itself for validation later on
_orderService = new Mock<IOrderService>();
var mockOrder = new Order();
_orderService.Setup(os => os.SearchByCode(It.IsAny<string>()))
.Returns(mockOrder);
}
private IContainer GetTestContainer()
{
// here we're adding just one registration we need, setting the mocked OrderService instance to be used for IOrderService
var builder = new ContainerBuilder();
builder.Register(c => _orderService.Object)
.As<IOrderService>();
return builder.Build();
}
[Fact]
public void SendEmail()
{
AutofacDependencyResolver.SetContainer(GetTestContainer()); // set the test container on the global singleton
var sender = new EmailSender();
sender.SendOrderEmail("abc"); // internally the email sender will retrieve the mock IOrderService via service location
// make any assertions here, e.g.
_orderService.Verify(os=>os.SearchByCode("abc"), Times.Exactly(1));
}
}

Using Methods not Defined in Interface on Fakes within Unit Tests

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.

Check if setup already exists for a Moq mock property?

I'm creating a private method in my unit test class that returns an object with mock dependencies, and I might provide some of those dependencies to the method, or I might not.
Consider the following method under test:
public IEnumerable<ServiceObject> GetSomeData(string query)
{
if (_currentEnvironment.Feeling == Feeling.Cooperative)
{
_dataGetter.GetData(query);
}
}
And a method to create an object with appropriately-setup mocks in my test class:
private DataService GetTestDataService(Mock<ExecutionEnvironment> mockEnvironment = null,
Mock<IDataGetter> mockDataGetter = null)
{
if (mockEnvironment == null)
{
mockEnvironment = new Mock<ExecutionEnvironment>();
}
if (mockDataGetter == null)
{
mockDataGetter = new Mock<IDataGetter>();
}
return new DataService(mockEnvironment.Object, mockDataGetter.Object);
}
I get in a bind when I need to setup the ExecutionEnvironment mock in my tests that need to step into the area where the GetData method is called. I need to have every one of those tests set it up to be feeling cooperative. If clauses are added to the "feeling cooperative" conditional, all of the tests will break until I change the setup in every test. I could create a separate method like CreateDefaultCurrentEnvironmentMock() that does some default setups, so my tests call that, then override the setups where they need to. However, what I'd like to have is all the logic in the same method, which can be accomplished by checking if a setup on the mock already exists, and do a setup if it hasn't been set up yet. Is this possible?

How to unit test web service with Linq

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.

How to create a Moq provider for Ninject?

I want to create a simple Ninject provider that returns Moq'd instances instead of concrete types. So far I have this:
public class NinjectMockProvider<T> : IProvider
{
public static Type Type { get { return typeof(T); } }
public object Create(IContext context)
{
Mock<T> newMock = new Mock<T>();
return newMock.Object;
}
}
But this is all wrong I'm sure as I don't know what I'm doing really. Any help and code samples would be great. I just want the ability to do:
kernel.Bind<ISomeInterface>().ToProvider<NinjectMoqProvider<ISomeInterface>>();
or something to that effect.
Update
I did figure out that I could accomplish what I want by using Ninject's method binding:
kernel.Bind<ISomeInterface>().ToMethod(x => new Mock<ISomeInterface>().Object);
I still would like a more elegant way and I may have to check out Ninject.Moq as suggested by Ian, but if anyone has any real code examples that would be awesome.
Does the MockingKernel extension handle what you need? It has Moq, RhinoMocks, and NSubstitute flavors, and it is also available on NuGet.
My solution to this always just uses the following:
MoqProvider
public class MoqProvider<T> : Provider<T> // T is the desired service
{
protected override T CreateInstance(IContext context)
{
return new Mock<T>().Object;
}
}
I then also register an IMissingBindingResolver with my kernel. The MoqMissingBindingResolver simply creates a new binding to a MoqProvider for any service for which a binding does not already exist.
MoqMissingBindingResolver
public class MoqMissingBindingResolver : NinjectComponent, IMissingBindingResolver
{
public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, IRequest request)
{
if (request.Service.IsAbstract || request.Service.IsInterface)
{
var moqProvider = (IProvider)Activator.CreateInstance(typeof(MoqProvider<>).MakeGenericType(request.Service));
return new IBinding[]
{
new Binding(request.Service, new BindingConfiguration
{
ProviderCallback = ctx => moqProvider,
ScopeCallback = Settings.DefaultScopeCallback
})
};
}
else
{
return Enumerable.Empty<IBinding>();
}
}
}
I typically also set Settings.DefaultScopeCallback to singleton so that I can request my mocked objects in my tests later on when I need to verify certain calls have or haven't taken place, or setup behaviour on mocks prior to executing the test. So setting up my kernel will look like the following:
INinjectSettings Settings = new NinjectSettings
{
DefaultScopeCallback = StandardScopeCallbacks.Singleton
};
var k = new StandardKernel(Settings);
k.Components.Add<IMissingBindingResolver, MoqMissingBindingResolver>();
Hope this is helpful.

Categories

Resources