Are those unit tests fine? - c#

I'm trying to grasp test driven development, and I'm wondering if those unit tests is fine. I have a interface which looks like this:
public interface IEntryRepository
{
IEnumerable<Entry> FetchAll();
Entry Fetch(int id);
void Add(Entry entry);
void Delete(Entry entry);
}
And then this class which implements that interface:
public class EntryRepository : IEntryRepository
{
public List<Entry> Entries {get; set; }
public EntryRepository()
{
Entries = new List<Entry>();
}
public IEnumerable<Entry> FetchAll()
{
throw new NotImplementedException();
}
public Entry Fetch(int id)
{
return Entries.SingleOrDefault(e => e.ID == id);
}
public void Add(Entry entry)
{
Entries.Add(entry);
}
public void Delete(Entry entry)
{
Entries.Remove(entry);
}
}
Theese are the unit tests I have written so far, are they fine or should I do something different? Should i be mocking the EntryRepository?
[TestClass]
public class EntryRepositoryTests
{
private EntryRepository rep;
public EntryRepositoryTests()
{
rep = new EntryRepository();
}
[TestMethod]
public void TestAddEntry()
{
Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
Assert.AreEqual(1, rep.Entries.Count, "Add entry failed");
}
[TestMethod]
public void TestRemoveEntry()
{
Entry e = new Entry { ID = 1, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
rep.Delete(e);
Assert.AreEqual(null, rep.Entries.SingleOrDefault(i => i.ID == 1), "Delete entry failed");
}
[TestMethod]
public void TestFetchEntry()
{
Entry e = new Entry { ID = 2, Date = DateTime.Now, Task = "Testing" };
rep.Add(e);
Assert.AreEqual(2, rep.Fetch(2).ID, "Fetch entry failed");
}
}
Thanks!

Just off the top of my head...
Although your testing of add really only tests the framework:
You've got adding 1 item, that's good
what about adding LOTS of items
(I mean, ridiculous amounts - for what value of n entries does the container add fail?)
what about adding no items? (null entry)
if you add items to the list, are they in a particular order?
should they be?
likewise with your fetch:
what happens in your fetch(x) if x > rep.Count ?
what happens if x < 0?
what happens if the rep is empty?
does x match performance requirements (what's it's algorithmic
complexity? is it within range when there's just one entry and when
there's a ridiculously large amount of entries?
There's a good checklist in the book Pragmatic Unit Testing (good book, highly recommended)
Are the results right?
Are all the boundary conditions CORRECT
Conform to an expected format
Ordered correctly
In a reasonable range
Does it Reference any external dependencies
Is the Cardinality correct? (right number of values)
does it complete in the correct amount of Time (real or relative)
Can you check inverse relationships
Can you cross check the results with another proven method
Can you force error conditions
Are performance characteristics within bounds

Here's some thoughts:
Positive
You're Unit Testing!
You're following the convention Arrange, Act, Assert
Negative
Where's the test to remove an entry when there's no entry?
Where's the test to fetch an entry when there's no entry?
What is supposed to happen when you add two entries and remove one? Which one should be left?
Should Entries be public. The fact that one of your asserts calls rep.Entries.SingleOrDefault suggests to me you're not constructing the class correctly.
Your test naming is a bit vague; typically a good pattern to follow is: {MethodName}_{Context}_{Expected Behavior} that remove the redundancy "test" redundancy.
As a beginner to TDD I found the book Test-Driven Development By Example to be a huge help. Second, Roy Osherove has some good Test Review video tutorials, check those out.

Before I answer, let me state that I am fairly new to unit testing and by no means an expert, so take everything I state with a grain of salt.
But I feel that your unit tests are largely redundant. Many of your methods are simple pass through, like your AddEntry method is simply a call to the underlying List method Add. Your not testing your code, your testing the Java library.
I would recommend only unit testing methods that contain logic that you write. Avoid testing obvious methods like getters and setters, because they operate at the most basic level. That's my philosophy, but I know some people do believe in testing obvious methods, I just happen to think it is pointless.

Seems fine like this. I personally like to give my tests a bit more descriptive names but that's more of a personal preference.
You can use mocking for dependencies of the class you're testing, EntryRepository is the class under test so no need to mock that, else you would end up testing the mock implementation instead of the class.
Just to give a quick example. If your EntryRepository would use a backend database to store the Entries instead of a List you could inject a mock-implementation for the data-access stuff instead of calling a real database.

This looks like a fine start, but you should try to test the 'borderline' cases as much as possible. Think about what might cause your methods to fail - Would passing a null Entry to Add or Delete be valid? Try to write tests that exercise every possible code path. Writing tests in this manner will make your test suite more useful in the future, should you make any changes to the code.
Also, it is useful for each test method to leave the test object in the same state as when it was invoked. I noticed your TestFetchEntry method adds an element to the EntryRepository, but never removes it. Having each method not affect test object state makes it easier to run series of tests.

You should not be mocking the IEntryRepository since the implementing class is the class under test. You might want to mock the List<Entry> and inject it, then just test that the methods that you invoke via your public interface are called appropriately. This would just be an alternative to the way you have it implemented and isn't necessarily better -- unless you want the class to have it's backing class injected in which case writing the tests that way would force that behavior.
You might want some more tests to make sure that when you insert an entry, the right entry is inserted. Likewise with delete -- insert a couple of entries, then delete one and make sure that the proper one has been deleted. Once you come up with tests to get the code to do what you want it to, keep thinking of ways that you could mess up writing the code and write tests to make sure those don't happen. Granted this class is pretty simple and you may be able to convince yourself that the tests you have that drive behavior is sufficient. It doesn't take much complexity, though, to make it worth testing edge cases and unexpected behavior.

For a TDD beginner and for this particular class, your tests are fine. +1 for making the effort.
Post another question once you get to more complex scenarios involving dependency injection and mocking. This is where things get really interesting ;).

Looks good overall. You should use transactions (or create new instance of repository in TestInitialize) to make sure the tests are trully isolated.
Also use more descriptive test methods, like When_a_new_entity_is_added_to_a_EntryRepository_the_total_count_of_objects_should_get_incremented

Related

How to Mock a Service with Moq and Nunit in mvc application - prevent nulls

I was under the impression that mocking is faking data calls thus nothing is real. So when I trying to create my own Unit Test that are very similar to what other developers on my team are doing, I am thinking that this is not correct to be newing up the service.
[Test]
public void TemplateService_UpdateTemplate_ContentNameNotUnique_ServiceReturnsError()
{
Template Template = new Template()
{
TemplateId = 123,
};
// Arrange.
TemplateUpdateRequest request = new TemplateUpdateRequest()
{
ExistingTemplate = Template
};
var templateRepo = new Mock<ITemplateRepository>();
var uproduceRepo = new Mock<IUProduceRepository>();
templateRepo.Setup(p => p.IsUniqueTemplateItemName(215, 456, "Content", It.IsAny<string>())).Returns(false);
templateRepo.Setup(p => p.UpdateTemplate(request)).Returns(1);
// Act.
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
TemplateResponse response = svc.UpdateTemplate(request);
// Assert.
Assert.IsNotNull(response);
Assert.IsNotNull(response.data);
Assert.IsNull(response.Error);
}
So my issue is with this code:
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
Should the TemplateService really be newed up? What "if" the Service ended up hitting a database and/or file system? Then it becomes an integration test, and no longer a unit test, right?
TemplateResponse response = svc.UpdateTemplate(request);
Also, how do I really control whether this is truly going to pass or not? It is relying on a service call that I didn't write, so what if there is a bug, or encounters a problem, or return NULL, which is exactly what I do not want! ?
If you're testing TemplateService, then YES it should be newed up. How else can you test your actual implementation? The point here is to only test TemplateService and not it's dependencies (unless it's an integrations test).
So if you got a repo like IUProduceRepository it should be mocked, simply to ensure that you're not writing to some database, and to make sure that you can create a specific scenario.
Your goal is to test that TemplateService is doing the right thing, based on a specific scenario. So let's say that your IUProduceRepository is throwing an error that your TemplateServiceshould handle. Then you should mock that error in your IUProduceRepository and test your implementation of TemplateService and make sure that it handles it as expected.
So to answer your questions...
Should the TemplateService really be newed up? What "if" the Service
ended up hitting a database and/or file system? Then it becomes an
integration test, and no longer a unit test, right?
Yes, I would say that it would be an integrations test. You mock things to make sure that the service isn't writing to DB.
Also, how do I really control whether this is truly going to pass or
not? It is relying on a service call that I didn't write, so what if
there is a bug, or encounters a problem, or return NULL, which is
exactly what I do not want! ?
Your goal is to make sure that the class you test is doing what you expect in a specific scenario. Let's say that your repo is throwing an exception for some reason, then you might want to test that your service can handle that (or at least test that it's doing what's expected).
public class TemplateService : ITemplateService
{
ITemplateRepository _templateRepo;
IUProduceRepository _produceRepo
public TemplateService(ITemplateRepository templateRepo, IUProduceRepository produceRepo)
{
_templateRepo = templateRepo;
_produceRepo = produceRepo;
}
public TemplateResponse UpdateTemplate(Template template)
{
try
{
var result = _templateRepo.Update(template);
return result;
}
catch(Exception ex)
{
// If something went wrong. Always return null. (or whatever)
return null;
}
}
}
[Test]
public void TemplateService_UpdateTemplate_ShouldReturnNullOnError()
{
Template template = new Template() // note that I changed the variable name.
{
TemplateId = 123,
};
// Arrange.
TemplateUpdateRequest request = new TemplateUpdateRequest()
{
ExistingTemplate = template
};
var templateRepo = new Mock<ITemplateRepository>();
var uproduceRepo = new Mock<IUProduceRepository>();
// Mock exception
templateRepo.Setup(p => p.UpdateTemplate(request)).Throw(new ArgumentException("Something went wrong");
// Act.
TemplateService svc = new TemplateService(templateRepo.Object, uproduceRepo.Object);
TemplateResponse response = svc.UpdateTemplate(request);
// Assert.
// Make sure that the exception is handled and null is returned instead.
Assert.IsNull(response);
}
The ONLY thing you actually tested in the case above is that your service will return null if there's an error in your repo. That way, you have designed a test for a specific scenario, and made sure that your service is doing what's expected when that scenario occurs.
I know that you specifically mentioned that you didn't want it to return null, but it's more of the concept I'm talking about. So let's say that the repo returns null... Write a test for it. Mock the repo to return null, and then test that your service is doing what it should (logging, etc).
so what if there is a bug, or encounters a problem, or return NULL,
which is exactly what I do not want! ?
That's what unit testing is all about. Find a scenario, and then make sure that the class you're testing is doing it's part. Mock your dependencies to create that specific scenario.
When I write my tests I have a lot of tests that simply asserts that a method was called. Let's say that I have a service, which only responsibility is to call the repo. Then you might want to write three tests
Test that the service actually calls the repo.
Test that the service does what it's suppose to with the value from the repo.
Test what happens if the repo throws an exception.
A unit test is designed to test a unit of functionality, which often is (but definitely need not be) a single class (since we should follow the Single Responsibility Principle). Therefore, it's fine to new up the class(es) that you're trying to test - it's the dependencies that you need to mock/stub out, which in your case is what you've done with the two repositories.
Whether your call
TemplateResponse response = svc.UpdateTemplate(request);
ends up hitting the DB is a question of using Dependency Injection correctly - your team needs to be disciplined in using explicit dependencies (ie. the repositories which are constructor injected), and not newing up repositories within a class.
And regarding whether your test is going to pass or not - if the class only has explicit dependencies (which are mocked out in your test), then only the logic within the call will be tested, which is exactly what you want!
I recommend you to read the book The Art of Unit Testing: with examples in C# to learn good practice.
In your example, you are testing TemplateService class.
Your concern is what if TemplateService calls database. It depends on how this class is implemented. From the example and mock setup, I can understand that the details of ITemplateRepository is responsible for database calling and that is why UpdateTemplate and IsUniqueTemplateItemName are mocked.
If you want to avoid the Null check, then you can check whether the svc.UpdateTemplate(request) calls the method UpdateTemplate of ITemplateRepository with its parameter.
It should be similar as follows
templateRepo.Verify(u => u.UpdateTemplate(It.Is<TemplateUpdateRequest>(r => r.ExistingTemplate.TemplateId == 123)),Times.Once);
You can verify other method calls that you have mocked.
Interaction testing is a form of unit testing where you provide fake dependencies for everything (or some things, or only the really expensive things like databases or disks, there are a lot of different interpretations regarding this) except the thing you actually want to test.
In your example, you're testing whether the TemplateService code behaves correctly. The test provides fake collaborators (the repositories), which you can setup so they return different things in different tests. That way, you can verify whether the TemplateService behaves correctly under these circumstances.
If your concerns about new-ing up the TemplateService are that there might be some remaining calls to a real database in the TemplateService code itself, that's a design issue of the TemplateService code. Those calls should not happen in the TemplateService but should be implemented on a collaborating object (exactly so you can fake them in focused isolated tests for your service).
Writing a unit test without new-ing up the system-under-test provides zero value. If every object is a fake, how can you test your actual production code?
On your point about how those mocked services are actually implemented (Do they throw nulls? Any bugs? Do they return NULL?), that's a question you can solve by
a) Writing integration tests (warning: this does not scale well, see related reading on why integrated tests are a scam).
or b) using something J.B. Rainsberger calls "Contract tests" (see related reading below) to verify whether the actual collaborator objects actually behave in a way consumers expect them to do.
Related reading:
Classicist vs. mockist testing in Martin Fowlers Mocks Aren't Stubs.
Integrated tests are a scam by J.B. Rainsberger
Contract tests by J.B.Rainsberger Who tests the contract tests?

how to organize test data in integration tests

I am working on a large test project consisting of thousands of integration tests.
It is a bit messy with lots of code duplication. Most tests are composed of several steps, and a lot of "dummy" objects are created. With dummy I mean something like this:
new Address {
Name = "fake address",
Email = "some#email.com",
... and so on
}
where it often really doesn't matter what the data is. This kind of code is spread out and duplicated in tests, test base classes, and helpers.
What I want is to have a single "test data builder", having a single responsibility, generate test data which is consumed by the tests.
One approach is to have a class with a bunch of static methods like following:
Something CreateSomething(){
return new Something {
// set default dummy values
}
and an overload:
Something CreateSomething(params){
return new Something {
// create the Something from the params
}
Another approach is to have xml files containing the data but i am afraid then it would be too far away from the tests.
The goal is to move this kind of code out of the tests because right now the tests are big and not readable. In a typical case, of 50 lines of test code, 20-30 is of this kind of code.
Are there any patterns for accomplishing this? Or any example of big open source codebase with something similar that I can have a look at?
For code, use a simple method chaining builder pattern:
public class TestOrderBuilder
{
private order = new Order();
// These methods represent sentances / grammar that describe the sort
// of test data you are building
public AnObjectBuilder AddHighQuantityOrderLine()
{
//... code to add a high quantity order line
return this; // for method chaining
}
// These methods represent sentances / grammar that describe the sort
// of test data you are building
public AnObjectBuilder MakeDescriptionInvalid()
{
//... code to set descriptions etc...
return this; // for method chaining
}
public Order Order
{
get { return this.order; }
}
}
// then using it:
var order = new TestOrderBuilder()
.AddHighQuantityOrderLine()
.MakeDescriptionInvalid()
.Order
I would shy away from xml files that specify test dependencies.
My thought process stems from a lack of refactoring tools that these xml files cannot take advantage of within the Visual Studio ecosystem.
Instead, I would create a TestAPI.
This API will be responsible for serving dependency data to test clients.
Note that the dependency data that is being requested will already be initialized with general data and ready to go for the clients that are requesting the dependencies.
Any values that serve as required test inputs for a particular test would be assigned within the test itself. This is because I want the test to self document its intent or objective and abstract away the dependencies that are not being tested.
XUnit Test Patterns provided me a lot of insight for writing tests.

Having difficulties setting up a mock to unit test WebAPI Post

I'm attempting to set up a unit test with MSTest and Moq for a live system that posts json from a form to a database. The system itself works just fine, but I've been tasked with attempting to build some tests for it. The ajax call in the view I'm working with goes to following HttpPost method one of the controllers:
[HttpPost]
public ActionResult Add(Request model)
{
return ProcessRequest(model, UserAction.Create);
}
Which leads to the WebAPI controller:
public int Post([FromBody]Request value)
{
try
{
var id = myRepository.AddRequest(value);
foreach (var day in value.Days)
{
day.RequestId = id;
myRepository.AddRequestDay(day);
}
return id;
}
catch
{
return -1;
}
}
With my test, I thought that using TransactionScope would be a good idea so I'm not actually saving any data on the database. If there is a better approach, please enlighten me:
[TestMethod]
public void API_Request_Post()
{
using (TransactionScope ts = new TransactionScope())
{
var jsonObject = //some json scraped from a test post
var request = new Mock<HttpRequestBase>();
//This is where I'm stuck. I can't find anything in Setup that lets me prep the Post body for when the controller gets to it.
//request.Setup(x => x.InputStream).Returns(jsonObject);
RequestController controller = new RequestController();
//This is another point that I don't understand. I make the call for post happy with a reference to the model instead of the actual json?
var result = controller.Post(new Models.Request() );
Assert.IsTrue(result > -1);
}
}
Any help trying to determine what part of the HttpRequest I need to give my json to would be greatly appreciated (and helping me understand the Post would just be icing on the cake).
Aside
I hope I'm not telling you something you already know, but it looks like you are maybe questioning where to start? That is the hardest part of testing...
Just to make sure we are on the same page, the key to knowing what to test is describing the scenario, and the key to unit testing that scenario is Isolation.
What this means is you want to isolate in regard to the class "under test".
Also, code is much easier to test if you write the test first and then the code to make that pass. You're not in that situation, so that means that the code you have MAY NOT be testable without changing it.
And finally, given any external / 3rd party system, unless you are doing an "exploratory test" then you do not want to test 3rd party stuff, namely, http posting / getting. Instead, you want to test your code and how it performs.
Assuming you knew that or that all makes sense, then, this part will be be obvious too.
Moq, or any other mocking framework, is designed to stand in for objects / services that your class under test collaborates with, in order to aid in isolation. Given two classes, ClassA and ClassB, where ClassA acts on ClassB, you want to fake/mock Class B when giving it to ClassA so you can assert / verify that ClassA behaves as you would expect for the given scenario. This seems naive at first, but consider that you will also do the same for ClassB, you then have a suite of tests that isolate in respect to what they are testing, and that gives you great coverage.
And the key to isolation is injection, make sure that if ClassA acts on ClassB, you pass ClassB in to ClassA's constructor, that way you can give it a fake class B. Class B shouldn't do anything, other than respond how you say it should respond so you can prove that ClassA behaves appropriately in that situation.
Some people frown on changing code to make it testable, but my argument is if you wrote the code to be testable in the first place, you wouldn't have to change it, so try to refactor but not reengineer.
What to Test
So, what that means is you will want a few different scenarios, each with each tests that isolate in respect to what you care about.
The key to good tests is figuring out what it is you want to test, and then arranging your tests so that it is clear what you are doing.
Test Class Name DOES NOT need to have "Test" in it; that's redundant. Explain what the scenario is instead; who is involved, etc.
The Test Method should say what the action is that you care about testing; what states are you in, etc.
** Inside the method** for now follow the "Arrange, Act, Assert" (aka Given, When, Then) approach:
Arrange: set up all of your mocks or any variables you need here, including the one class you are testing, such as your real Controller but fake myRepository and fake value
Act: do the actual action, such as Post()
Assert: Prove that the behaviors you expected happened, such as when you give it a value with four days, then you expect that:
myRepository was told to add the value
myRepository was told to add a day four times
An Example
As I'm not entirely sure what the intent of the test is there, and I don't know all of the code, I'm going to give an example that I think will relate well and will hopefully also show how to set up the mocks (and ideally why you would!)
Also if this were truly a unit test, you would usually strive for one test per assertion / verification so you do not have to debug the test, only the failing code, but I'm putting three in here for "simplicity".
In this test, you'll see that I:
Care about testing the logic in POST
So I create a mocked repository that is only used for verification it was called,
And a mocked Request that is setup to respond appropriately when called,
And I pass the mocked repository to the Controller's constructor (isolation through injection)
And then I perform the action I care about, POST, on the live controller with mocked collaborators (repository and request),
And then I verify that POST performs / behaves as expected.
[TestClass]
public class GivenAValidRequestAndRepository(){
[TestMethod]
public void WhenWeReceiveAPostRequest(){
//Arrange / Given
var repository = new Mock<IRepository>();
var request = new Mock<IRequest>();
request.Setup ( rq => rq.ToString() )
.Returns ( "This is valid json ;-)" );
request.Setup ( rq => rq.Days )
.Returns ( new List<IDay> {
"Monday",
"Tuesday",
} );
var controller = new RequestController( repository.Object );
//Act / When
int actual = controller.Post( request.Object );
//Assert / Verify
// - then we add the request to the repository
repository.Verify(
repo => repo.AddRequest( request, Times.Once() );
// - then we add the two days (from above setup) in the request to the repository
repository.Verify(
repo => repo.AddRequestDays( It.IsAny<IDay>(), Times.Exactly( 2 ));
// - then we receive a count indicating we successfully processed the request
Assert.NotEqual( -1, actual );
}
}
Closing
Your goal should not be to make your boss happy that you have written a test. Instead, strive for valuable and expressive tests that you will be able to maintain down the road. You won't get it perfect (nor should you try) just make sure that what you are testing adds value. Cover things that if they were to change in code, your test would then fail, indicating you have a bug.
I hope this helps, please reply with comments / questions.

Unit Testing Methods With File IO

I'm trying to get into the habit of writing unit tests, I've written a few before but they've usually been quite basic...I'd like to start making a move to TDD as i want to improve the quality of my code (design and structure) - reducing coupling, while at the same time hopefully reduce number of regressions which slip through to a testable build.
I have taken a relatively simple project i work on to begin with. The resultant program watches a folder and then acts on files within this folder.
Here is a typical example of some code extracted from the project:
private string RestoreExtension(String file)
{
var unknownFile = Path.GetFileName(file);
var ignoreDir = Path.GetDirectoryName(file) + "\\Unknown";
string newFile;
//We need this library for determining mime
if (CheckLibrary("urlmon.dll"))
{
AddLogLine("Attempting to restore file extension");
var mime = GetMimeType(BufferFile(file, 256));
var extension = FileExtensions.FindExtension(mime);
if (!String.IsNullOrEmpty(extension))
{
AddLogLine("Found extension: " + extension);
newFile = file + "." + extension;
File.Move(file, newFile);
return newFile;
}
}
else
{
AddLogLine("Unable to load urlmon.dll");
}
AddLogLine("Unable to restore file extension");
if (!Directory.Exists(ignoreDir))
{
Directory.CreateDirectory(ignoreDir);
}
var time = DateTime.Now;
const string format = "dd-MM-yyyy HH-mm-ss";
newFile = ignoreDir + "\\" + unknownFile + "-" + time.ToString(format);
File.Move(file, newFile);
return String.Empty;
}
Questions :
How can i test a method using IO?
I don't really want to be using a real file as this would be slow (and more of an integration test?), but i cant really see another way. I could add a switchable IO abstraction layer, but this sounds to me like it may unnecessarily complicate code...
Is a project like this worth unit testing?
By that i mean, is it too simple. Once you strip out .Net and 3rd party library calls there is not much left...So is it a case that the amount of work to make it testable means its not a good candidate to test?
A lot of the methods in this project are private, as this project happens to be a windows service. I've read you should only really test methods which are externally visible (public or exposed through an interface), it is unlikely in this case however that i want to expose any of my own methods. So is this project worth testing (as id probably need to either change method access modifiers to public or add some attributes so that NUnit can see them)?
Regarding how to test File I/O:
A common way of doing this is encapsulating File I/O in a wrapper class. For example:
public class FileHandler : IFileHandler
{
public string GetFilename(string name)
{
return System.IO.GetFileName(name);
}
public string GetDirectoryName(string directory)
{
return System.IO.GetDirectoryName(directory);
}
}
public interface IFileHandler
{
string GetFilename(string name);
string GetDirectoryName(string directory);
}
In your method under test, you only program against the interface. When you run your unit test, you would use a mock object which returns predefined values. For this, you could use Moq.
This is a bit work to do but then you do not need to test File I/O as well.
Best
Jan
How can i test a method using IO?
By introducing abstraction over the .NET's IO libraries and then using real implementation (BCL) in application, and fake (mocked) one in unit test. Such abstraction is fairly simple to write on your own, but those projects already exist (eg. System.IO.Abstraction) so reinventing wheel is pointless, especialy in such trivial matter.
I don't really want to be using a real file as this would be slow
This is correct, in test you want to use fake (mock) objects.
Is a project like this worth unit testing?
Every project is worth testing and you will test it in one way or another (in most extreme case, by manually executing application and doing good, old click-and-wait testing).
Note that almost always it is too time consuming to manually test 10 edge cases of complex parser method which everytime requires you to load large file and wait for results. This is where automated tests in isolated environment help greatly. It is the same with your code - file system, web service, they all introduce large overhead before you can get to actual business logic. Must isolate.
A lot of the methods in this project are private (...) I've read you should only really test methods which are externally visible
Correct again, you should be testing public contract. However, if private stuff gets big enough to test it, most of the times it's a good indicator it is also big enough to put it in its own class. Note that changing members access modifiers only for the unit test usage is not the best idea. Almost always it's better to extract-class/method refactor.
You can do that using Microsoft Fakes. First generate a fake assembly for System.dll - or any other package and then mock expected returns as in:
using Microsoft.QualityTools.Testing.Fakes;
...
using (ShimsContext.Create())
{
System.IO.Fakes.ShimDirectory.ExistsString = (p) => true;
System.IO.Fakes.ShimFile.MoveStringString = (p,n) => {};
// .. and other methods you'd like to test
var result = RestoreExtension("C:\myfile.ext");
// then you can assert with this result
}
I'm pretty new with TDD too, but I think I can get some suggestion to you:
About IO testing. You can use mock objects. Create a mock for the method you want to test and compare it with real passed in value. In Moq Framework it looks like that:
var mock = new Mock<IRepository<PersonalCabinetAccount>>();
mock.Setup(m => m.RemoveByID(expectedID))
.Callback((Int32 a) => Assert.AreEqual(expectedID, a));
var account = new PersonalCabinetAccount {ID = myID};
var repository = mock.Object;
repository.RemoveByID(account.myId);
Absolutely, yes. If you want to get a habit, you need to test everything, i suppose. That way knowledge comes ;)
You can use InternalsVisibleTo attribute to avoid visibility issues.
test methods which are externally visible
I think this one about enterprise programming. just a spare of time with your own trusted code.
Hope my point can help you.

Unit Testing Database-Modifying functions?

I have methods like this:
public static bool ChangeCaseEstimatedHours(int caseID, decimal? time)
{
Case c = Cases.Get(caseID);
if (c != null)
{
c.EstimatedHours = time;
return Cases.Update(c);
}
return false;
}
public static bool RemoveCase(int caseID)
{
return Cases.Remove(caseID);
}
which internally uses LINQ to do the queries.
I am wondering how I should go about testing these. They do not have a state so they are static. They also modify the database.
Thus, I would have to create a case, then remove it in the same test, but a unit test should only be doing 1 thing. What is usually done in these situations?
How do I test database queries, updates and deletes?
Thanks
A test that requires database access is probably the hardest test to maintain. If you can avoid touching the database in your unit test, I would try to create an interface for the Cases class.
interface ICase
{
ICase Get(int caseID);
bool RemoveCase(int caseID);
}
And then use RhinoMock, Moq to verify if the Get() and RemoveCase() were called.
If you insist you need to test with a database, then you will need to spend time on setting up a testing database and do proper data clean up.
There is a difference between "Knowing the path and walking the path". What you want to test would class as an integration test not a unit test. A unit test is something that is carried out in isolation without any external dependencies and therefore makes the test runnable even if the machine you are running it on does not have a physical database instance present on it. See more differences here.
That's why patterns like Repository are really popular when it comes to doing persistence based applications as they promote unit test-ability of the data layer via Mocking. See a sample here.
So, you have 2 options (the blue pill Or the red pill):
Blue Pill: Buy a tool like TypeMock Isolator essential or JustMock and you'll be able to mock anything in your code "and the story ends".
Red Pill: Refactor existing design of the data layer to one of the interface based patterns and use free Mocking frameworks like Moq or RhinoMocks and "see how deep the rabbit hole goes"
All the best.
Maybe you could consider approach based on Rails framework:
Initialize database tables content via presets (fixtures in Rails)
Open transaction
Run test
Rollback transaction
Go to point 2. with another test

Categories