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.
Related
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
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 an item and I am adding it to the database using this method:
public Messages addItem(Item item)
{
Messages resultMessage = Messages.Success;
using (IUnitOfWork unitOfWork = new UnitOfWork())
{
IItemRepository itemRep = new ItemRepository(unitOfWork);
try
{
itemRep.Insert(item);
unitOfWork.Commit();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
resultMessage = Messages.DB_Failure;
}
}
return resultMessage;
}
Now I have to make write a unit test for this method to check if the item is being added to the database. I have no idea how I should do that, can someone help me?
Your code is coupled with the ItemRepository and the UnitOfWork implementations. Ideally you should decouple them and use mocks to verify that the right methods are called.
A possible solution:
Make the Repository a property on your unit of work
Don't create the Unit of Work directly, use a factory for that
Make the factory a dependency of your class
In your test pass a mock of the factory to the class you are testing that returns a mock of the Unit Of Work
Return a mock of the Repository on your UoW mock
Verify that the right methods are called on your Repository mock and Unit of Work mocks
This would be an example. I have used Moq as the mocking framework. And put the test method inside the class, but you can get the idea:
class MyClass
{
private readonly IUnitOfWorkFactory _factory;
public MyClass(IUnitOfWorkFactory factory)
{
_factory = factory;
}
public Messages addItem(Item item)
{
Messages resultMessage = Messages.Success;
using (IUnitOfWork unitOfWork = _factory.GetUnitOfWork())
{
try
{
unitOfWork.ItemRep.Insert(item);
unitOfWork.Commit();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
resultMessage = Messages.DB_Failure;
}
}
return resultMessage;
}
public void Test()
{
// Arrange
var factoryMock = new Mock<IUnitOfWorkFactory>();
var uowMock = new Mock<IUnitOfWork>();
var repositoryMock = new Mock<IItemRepository>();
factoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
uowMock.Setup(u => u.ItemRep).Returns(repositoryMock.Object);
var sut = new MyClass(factoryMock.Object);
// Act
var item = new Item();
sut.addItem(item);
// Assert
repositoryMock.Verify(r => r.Insert(item), Times.Once);
uowMock.Verify(u => u.Commit(), Times.Once);
}
}
You say that the goal is to "check if this item is added to the database".
This is something you do not normally write a unit test for because it is the responsibility of the database, which presumably you are not the one developing.
A better case for a unit test is to mock out the database and check the logic that decides to add something to the database. For instance:
A Unit of Work is described by a customer/operator.
Your component queries the database for the existence of the item.
No corresponding item exists.
Your component adds the item to the database.
This is achieved by using just a mock of the database and it is testing your code, rather than the database.
As your method currently stands, it cannot be unit tested as it's hard-coded to write to the database.
The conventional way around this is to pass an instance of IItemRepository into the method, rather than having the method create it. Do that and then you are free to create a mocked IItemRepository implementation that can report what's being written to the DB.
As other answers suggested: try to separate your class under test from difficult/slow to test dependencies like the database. You can use a number of approaches to achieve this result, but they all come down to the same:
Don't create (new up) dependencies that make unit testing difficult in the code you want to test itself (like your unitofwork/repository). Rather, ask these dependencies from the outside world (google Dependency Inversion/DI for further info).
If you want to test the implementation of the repository with a real database, I suggest you test through the public API of your repository. Don't go writing "SELECT * FROM Items" queries yourself, but use a repository.GetItem(...) method if available. That way your tests are less brittle and decoupled from the actual implementation of your repository class.
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.
I have an application in VB/C# .NET which needs to interact with a third party API, but I would like to interface it out so I can use a mock API for testing purposes. Here are example API calls I would use in code:
RelayClient.AuthenticateUser(username, password, request, sessionID)
RelayClient.GetUserInfo(sessionID)
A few problems I am facing:
RelayClient is NonInheritable/Static.
RelayClient doesn't implement any interfaces.
The API client library is closed source.
Is there any standard way of dealing with this situation?
The way to do this would be to make your code work against 'middle-man' non-static classes, which internally use the static classes from your 3rd party API. You then mock out these 'middle-man' classes for your unit tests.
Something like... (untested code)
// your consuming class
public class MyClass
{
private readonly RelayClientManager manager;
public MyClass(RelayClientManager manager)
{
this.manager = manager;
}
public UserInfo GetUserInfo(int sessionID)
{
return manager.GetUserInfo(sessionID);
}
}
// 'middle-man' class
public class RelayClientManager
{
public UserInfo GetUserInfo(int sessionID)
{
return RelayClient.GetUserInfo(sessionID);
}
}
// unit test (using xUnit.net and Moq)
[Fact]
public static void GetsUserInfo()
{
// arrange
var expected = new UserInfo();
var manager = new Mock<RelayClientManager>();
manager.Setup(x => x.GetUserInfo(0)).Returns(expected);
var target = new MyClass(manager);
// act
var actual = target.GetUserInfo(0);
// assert
Assert.Equal(expected, actual);
}
If you don't want to roll your own abstraction, have a look at TypeMock Isolator- it uses profiler hooks to do runtime class-level mocking of pretty much anything, whether you own it or not. It actually does a runtime substitution of the type implementation and intercepts all the calls (eg, you don't need to subclass the type- as far as the CLR is concerned, you ARE the type).
It's commercial, but they do have a free trial. Depending on how big the thing you need to mock is, the $799 can be well worth the time abstracting/wrapping the entire API surface if it's not interface-based.