Setup on Mock not returning expected value - c#

Here is a simplified version of a problem I encountered:
public interface IService
{
IProvider Provider { get; }
}
public interface IProvider
{
List<int> Numbers{ get; }
string Text { get; }
}
[TestMethod]
public void ServiceTest()
{
var service = new Mock<IService>();
var provider = new Mock<IProvider>();
service.Setup(s => s.Provider).Returns(provider.Object); // A
service.Setup(s => s.Provider.Text).Returns("some text"); // B - incorrect
// they actually meant to do this, instead of 'B'
// provider.Setup(p => p.Text).Returns("some text");
provider.Setup(p => p.Numbers).Returns(new List<int> { 1, 2, 3 });
DummyApplicationCode(service.Object);
}
int DummyApplicationCode(IService service)
{
// will throw, because the Provider was replaced at 'B'
int shouldBeOne = service.Provider.Numbers.First();
return shouldBeOne;
}
A unit test was failing because way down in the application code under test, the mocked IService was returning the wrong IProvider.
I eventually spotted the line (bear in mind the code I was looking at was not as simple as above) which had caused it, labelled 'B' above, which someone else had added due to misunderstanding the Moq Setup.
I'm aware that subsequent Setups on a mock will override previous ones but I hadn't spotted this issue because the Return of the offending line was for a separate sub-property.
I expect this is by design but it threw me as I hadn't anticipated someone would do this.
My question: Since the Setup at 'B' is only concerned with the return of the provider Text, why does the service 'Provider' property need to replace that which was defined at 'A'?

This is clearly intentional when looking at the source:
https://github.com/moq/moq4/blob/master/Source/Mock.cs
https://github.com/moq/moq4/blob/master/Source/Interceptor.cs
Setup creates a "call" by using AddCall on Interceptor. This contains the following block of code which, as long as we're creating a non-conditional setup, removes all previous setups. It's even commented.
if (!call.IsConditional)
{
lock (calls)
{
// if it's not a conditional call, we do
// all the override setups.
// TODO maybe add the conditionals to other
// record like calls to be user friendly and display
// somethig like: non of this calls were performed.
if (calls.ContainsKey(key))
{
// Remove previous from ordered calls
InterceptionContext.RemoveOrderedCall(calls[key]);
}
calls[key] = call;
}

Related

How to mock Func<Enum, Interface>() parameter in constructor of the tested class (sut)

In my .Net6 web app, I attempted to register service injection for 2 implementations of a single IWordRepository Interface:
WordRepositoryInMemory, working with in-memory data;
WordRepositoryDatabase with calls to the database;
Following the example set out in this article, I created an enum:
public enum WordRepositoryImplementation
{
WordRepositoryInMemory,
WordRepositoryDatabase
}
Then, in my Program.cs, I registered the two services:
builder.Services.AddScoped<WordRepositoryDatabase>();
builder.Services.AddScoped<WordRepositoryInMemory>();
builder.Services.AddTransient<Func<WordRepositoryImplementation, IWordRepository?>>(wordRepositoryProvider => key =>
{
return key switch
{
WordRepositoryImplementation.WordRepositoryInMemory => wordRepositoryProvider.GetService<WordRepositoryInMemory>(),
WordRepositoryImplementation.WordRepositoryDatabase => wordRepositoryProvider.GetService<WordRepositoryDatabase>(),
_ => null,
};
});
Then, I called it in my controller like so:
private readonly IWordRepository _wordRepositoryDatabase; // I only require one of the implementations to be called by this controller.
public DictionaryDataController(Func<WordRepositoryImplementation, IWordRepository> serviceResolver)
{
_wordRepositoryDatabase = serviceResolver(WordRepositoryImplementation.WordRepositoryDatabase);
}
Unfortunately, this added complexity messed up my tests for the controller. I am no longer able to instantiate the sut with a simple Mock.Object of the WordRepositoryDatabase service. By saying unable, I mean that I don't quite have the required experience handling delegates, yet.
In my test fixture, I tried to replace the original mock implementation of the service:
private Mock<IWordRepository> _wordRepository;
// ....
_wordRepository= new Mock<IWordRepository>();
// ....
DictionaryDataController sut = new(_wordRepositoryDatabase.Object);
To something that returns a Mock of the IWordRepository, so that I could use it in my constructor:
private Func<WordRepositoryImplementation, IWordRepository?> _funcWordRepositoryImplementation;
// ...
// ...
DictionaryDataController sut = new(_funcWordRepositoryImplementation);
However, I cannot grasp the required syntax here. The closest I got to was a parameterless Func<>() that returned the Mock.Object, but it was clearly missing something.
_funcWordRepositoryImplementation= () =>
{
return new Mock<WordRepositoryImplementation, IWordRepository>();
};
And attempts to pass some arguments to it caused their own set of errors.
What would the correct way to set up this field be?
Just use lambda expression with discard parameter which will return _wordRepositoryDatabase.Object:
DictionaryDataController sut = new(_ => _wordRepositoryDatabase.Object);

Should unit tests tests the functionality of a method? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am writing unit tests but the part that confuses me most is whether it should test the functionality or not?
For example, if there is a method which does two things
Deletes files from a folder
Returns whether the folder is empty or not
public bool DeleteFTPFiles(string xyz)
{
...
path = GetFTPPath(xyz);
DeleteFolderFiles(path);
return IsFtpFolderEmpty(path);
}
DeleteFolderFiles - deletes files based on some logic.
Now, if I have to do unit testing for this method(DeleteFTPFiles).
Do I have to create folder structure and add some files through my unit tests as an Arrange test?
Assert whether files are deleted based on the condition?
Also, test if IsFtpFolderEmpty returns true or false based on whether it is empty or not?
If so, how is this different from Integration tests?
For example, if there is a method which does two things
The method you've chosen to write DeleteFTPFiles() is a poor choice because the result does not match the name. If the file is not deleted, the method may still return true? That's faulty logic. If I used that code, I would assume the result is if the file was or wasn't deleted, not if the directory was empty.
If I were to write it, it would just be DeleteAllFiles(), because it doesn't need to know where it happening, just that it is. I would then pass in another class that is has the method necessary to do the work.
public class MySpaceManager()
{
private readonly IFileManager _fileManager;
public MySpaceManager(IFileManager fileManager)
{
_fileManager = fileManager;
}
public bool TryDeleteAllFiles1(logicalDirectory)
{
var files = _fileManager.GetFiles(logicalDirectory);
var result = true;
foreach(var file in files)
result = result && _fileManager.Delete(file);
return result;
}
// or maybe
public bool TryDeleteAllFiles2(logicalDirectory)
{
var files = _fileManager.GetFiles(logicalDirectory);
foreach(var file in files)
_fileManager.Delete(file);
var result = _fileManager.GetFiles(logicalDirectory).Count() == 0;
return result;
}
}
Should unit tests tests the functionality of a method?
Here is my explanation:
A unit-test should only test what it's meant to encapsulate. This may include one or more of the following (not necessarily an exhaustive list):
Runs to Completion
Throws an Exception
Some type of logic (eg. AddTwoNumber() does indeed do that logic)
Executes some external dependency
Does not execute some external dependency
Lets take this hypothetical class and break down what and why each is tested:
public class MySpaceManagerTests
{
// First simple, best good path for code
public void TryDeleteAllFiles2_WithEmptyPath_ThrowsNoException()
{
/// ** ASSIGN **
// I'm using NSubstitute here just for an example
// could use Moq or RhinoMocks, whatever doesn't
// really matter in this instance
// the important part is that we do NOT test dependencies
// the class relies on.
var fileManager = Substitute.For<IFileManager>();
fileManager
.GetFiles(Args.Any<string>())
.Returns(new List<IFile>());
var mySpaceManager = new MySpaceManager(fileManager);
// ** ACT && ASSERT**
// we know that the argument doesn't matter so we don't need it to be
// anything at all, we just want to make sure that it runs to completion
Asser.DoesNotThrow(() => mySpaceManager.TryDeleteAllFiles2(string.Empty);
}
// This looks VERY similar to the first test but
// because the assert is different we need to write a different
// test. Each test should only really assert the name of the test
// as it makes it easier to debug and fix it when it only tests
// one thing.
public void TryDeleteAllFiles2_WithEmptyPath_CallsFileManagerGetFiles()
{
/// ** ASSIGN **
var fileManager = Substitute.For<IFileManager>();
fileManager
.GetFiles(Args.Any<string>())
.Returns(new List<IFile>());
var mySpaceManager = new MySpaceManager(fileManager);
// ** ACT **
mySpaceManager.TryDeleteAllFiles2(string.Empty)
// ** ASSERT **
Assert.DoesNotThrow(fileManager.Received().GetFiles());
}
public void TryDeleteAllFiles2_With0Files_DoesNotCallDeleteFile
{
/// ** ASSIGN **
var fileManager = Substitute.For<IFileManager>();
fileManager
.GetFiles(Args.Any<string>())
.Returns(new List<IFile> { Substitute.For<IFile>(); });
var mySpaceManager = new MySpaceManager(fileManager);
// ** ACT **
mySpaceManager.TryDeleteAllFiles2(string.Empty)
// ** ASSERT **
Assert.DoesNotThrow(fileManager.DidNotReceive().GetFiles());
}
public void TryDeleteAllFiles2_With1File_CallsFileManagerDeleteFile
{
// etc
}
public void TryDeleteAllFiles2_With1FileDeleted_ReturnsTrue()
{
/// ** ASSIGN **
var fileManager = Substitute.For<IFileManager>();
fileManager
.GetFiles(Args.Any<string>())
.Returns(new List<IFile> { Substitute.For<IFile>(); },
new list<IFile>());
var mySpaceManager = new MySpaceManager(fileManager);
// ** ACT **
var actual = mySpaceManager.TryDeleteAllFiles2(string.Empty)
// ** ASSERT **
Assert.That(actual, Is.True);
}
public void TryDeleteAllFiles2_With1FileNotDeleted_ReturnsFalse()
{
/// ** ASSIGN **
var fileManager = Substitute.For<IFileManager>();
fileManager
.GetFiles(Args.Any<string>())
.Returns(new List<IFile> { Substitute.For<IFile>(); },
new List<IFile> { Substitute.For<IFile>(); });
var mySpaceManager = new MySpaceManager(fileManager);
// ** ACT **
var actual = mySpaceManager.TryDeleteAllFiles2(string.Empty)
// ** ASSERT **
Assert.That(actual, Is.False);
}
}
Unit-test may test this code but it should be written a little another way.
Looking at this code rather make sense to talk about integration tests not unit-tests.
To have ability to write unit-test need to decouple your code from concrete implementations. You want test your code not FTP-service, is'n it?
To make code testable need to refactor your code following these steps:
Introduce the IFileStorage-abstraction:
public interface IFileStorage
{
string GetPath(string smth);
void DeleteFolder(string name);
bool IsFolderEmpty(string path);
}
public sealed class FtpFileStorage : IFileStorage
{
public string GetPath(string smth) { throw new NotImplementedException(); }
public void DeleteFolder(string name) { throw new NotImplementedException(); }
public bool IsFolderEmpty(string path) { throw new NotImplementedException(); }
}
Code should depend from abstractions not concrete implementations:
public class SmthLikeServiceOrManager
{
private readonly IFileStorage _fileStorage;
public SmthLikeServiceOrManager(IFileStorage fileStorage)
{
_fileStorage = fileStorage;
}
public bool DeleteFiles(string xyz)
{
// ...
var path = _fileStorage.GetPath(xyz);
_fileStorage.DeleteFolder(path);
return _fileStorage.IsFolderEmpty(path);
}
}
Now you can write real unit-test using one of the mocking libraries such as
Moq
NSubstitute
Related articles on StackOverflow:
Mocking using Moq in c#
..

Replacing the value of Setup with Moq

I'm mocking a DbContext and its DbSets as described here.
I'd like to create a utility method for creating my mock DbContexts, which sets up each of the context's DbSets to return an empty list by default (otherwise I get errors about null references whenever I try to query one of the DbSets). Then in unit tests where I want non-empty data in a certain DbSet, I want to call Setup again on that DbSet to supply that value than I want returned. Code is below.
I did this in a unit test and it appears to be working, but I can't find anything about how Moq handles calling Setup twice on the same property. Is doing this OK, or will it have unexpected side effects? Using the debugger, I looked into context.Setups, and calling Setup a second time on the same property adds a second object to Setups rather than overwriting the first one, which worries me.
[TestClass]
public class MyTests
{
// Creates a new Mock<MyContext> and calls Setup on each property so
// that they all return empty lists
private Mock<MyContext> CreateContext()
{
Mock<MyContext> context = new Mock<MyContext>();
// CreateMockDbSet is a utility method which creates a Mock<DbSet<TEntity>>
// as described in the MSDN article listed above
context.Setup(e => e.Customers).Returns(CreateMockDbSet<Customer>().Object);
context.Setup(e => e.Orders).Returns(CreateMockDbSet<Order>().Object);
return context;
}
[TestMethod]
public void MyTest()
{
// By default, context.Customers and context.Orders will both return
// empty DbSets
Mock<MyContext> context = CreateContext();
List<Order> orders = new List<Order>
{
new Order { Id = 1 },
new Order { Id = 2 },
new Order { Id = 3 }
};
// CreateMockDbSet creates a Mock<DbSet<Order>> which returns the orders
// in 'orders'. What does Moq do when I call Setup again on 'Orders'?
context.Setup(e => e.Orders).Returns(CreateMockDbSet(orders).Object);
// ... Do test ...
}
}
https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx
If you create a subsequent setup on a method and it's non-conditional (no constraints on the arguments) then it removes all previous setups for the method.
In your case where you don't have a method accepting arguments then you obviously can't add any constraints on them, so your subsequent setup will just replace the previous.
See this answer for an explanation of the source code.

How to verify method parameters with FakeItEasy as well as that a call has been made

I'm using FakeItEasy to do some testing, but I have run into a problem.
When testing that the expected data is sent to a faked service, I would like to be able to see the error data as well.
Right now I only see that the call never happened.
Maybe I'm setting it up all wrong, but then I'd like some hints on how to correct it. :)
My case is:
A call to the same service twice, with different values.
I want separate tests to verify each call.
If any of the parameters, doesn't have the expected value, I would like to get an error message stating that. Similar to when you do an Assert.AreEqual().
Right now I only get "Call did not happen", which is totally understandable, because I realise that is what I'm testing. But I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I used this solution: http://thorarin.net/blog/post/2014/09/18/capturing-method-arguments-on-your-fakes-using-fakeiteasy.aspx
when I only had one call, but with two calls it doesn't work.
[TestFixture]
public class TestClass
{
[Test]
public void TestOne()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 2))).MustHaveHappened(Repeated.Exactly.Once);
}
[Test]
public void TestTwo()
{
// Arrange
var fake = A.Fake<IBarservice>();
var a = new Foo(fake);
// Act
a.DoStuff(1);
//Assert
A.CallTo(() => fake.DoOtherStuff(A<int>.That.Matches(x => x == 3))).MustHaveHappened(Repeated.Exactly.Once);
}
}
public class Foo
{
private readonly IBarservice _barservice;
public Foo(IBarservice barservice)
{
_barservice = barservice;
}
public void DoStuff(int someInt)
{
someInt++;
_barservice.DoOtherStuff(someInt);
// I should have increased someInt here again, but this is a bug that my tests catches
_barservice.DoOtherStuff(someInt);
}
}
public interface IBarservice
{
void DoOtherStuff(int someInt);
}
Markus, I had a comment that I've redacted, since I made an error.
You say you only get "Call did not happen" and
… I would like to be able to verify that a specific call has only been made once, and if it did not happen I would like to see which values were used to not make it happen.
I fear I don't understand what information you were hoping for, since when I run TestOne, I get
FakeItEasy.ExpectationException
Assertion failed for the following call:
FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(<x => (x == 2)>)
Expected to find it exactly once but found it #2 times among the calls:
1: FakeItEasyQuestionsVS2015.IBarservice.DoOtherStuff(someInt: 2) repeated 2 times
...
This says that the call DoOtherStuff was made twice, with someInt passed in as the value 2 each time.

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.

Categories

Resources