I have a method similar to this:
public List<MyClass> DoSomething(string Name, string Address, string Email, ref string ErrorMessage)
{
//Check for empty string parameters etc now go and get some data
List<MyClass> Data = GetData(Name, Address, Email);
/*************************************************************
//How do I unit test that the data variable might be empty???
*************************************************************/
List<MyClass> FormattedData = FormatData(Data);
return FormattedData;
}
I'm just learning TDD/Unit Testing. My question is, how do I write a test to ensure that if GetData returns an empty list I set ErrorMessage to something and then return a empty list?
When developing you should have left an "entrance point" for testing like this:
public List<MyClass> DoSomething(string Name, string Address,
string Email, ref string ErrorMessage, IDataProvider provider)
{
//Check for empty string parameters etc now go and get some data
List<MyClass> Data = provider.GetData(Name, Address, Email);
List<MyClass> FormattedData = FormatData(Data);
return FormattedData;
}
And in the Unit Testing you should mock
the IDataProvider
It's called Dependency Injection (DI) or Inversion Of Control (IOC)
The list was taken from here
[Test]
public void When_user_forgot_password_should_save_user()
{
// Arrange
var errorMessage = string.Empty;
var dataProvider = MockRepository.GenerateStub<IDataProvider>();
dataProvider.Stub(x => x.GetData("x", "y", "z", ref errorMessage )).Return(null);
// Act
var result DoSomething("x","y","z", ref errorMessage, dataProvider);
// Assert
//...
}
Unit testing is not something you add to the middle of existing methods, it is about testing small units of code in isolation from the rest of the system such that you have confidence that the unit is behaving as it should.
So, you should write a second class that's sole responsibility is to test that the class in which DoSomething
lives (let's call this class Daddy
and the test class DaddyTests
) behaves as you expect it to. You can then write a test method that calls DoSomething
and ensures that ErrorMessage
is set appropriately (also ErrorMessage
should be an out
param, not ref
unless you are also passing a value in).
To facilitate this test you will need to make sure that GetData
returns no data. Trivially you can do this by passing in an empty set of data in a fake provider but in more complex scenarios whole classes may have to be swapped out for fake/mock equivalents: the use of interfaces and dependency-injection makes this task very simple. (Typically the provider is set during Daddy
's construction, not as a parameter in the call to DoSomething
.)
public class Daddy {
public List<MyClass> DoSomething(string Name, string Address, string Email, out string ErrorMessage, IDataProvider provider)
{
//Check for empty string parameters etc now go and get some data
List<MyClass> Data = provider.GetData(Name, Address, Email);
if (Data.Count == 0)
{
ErrorMessage = "Oh noes";
return Enumerable.Empty<MyClass>();
}
List<MyClass> formattedData = FormatData(Data);
return formattedData;
}
}
[TestClass]
public class DaddyTest {
[TestMethod]
public void DoSomethingHandlesEmptyDataSet() {
// set-up
Daddy daddy = new Daddy();
// test
IList<MyClass> result = daddy.DoSomething("blah",
"101 Dalmation Road",
"[email protected]",
out error,
new FakeProvider(new Enumerable.Empty<AcmeData>())); // a class we've written to act in lieu of the real provider
// validate
Assert.NotNull(result); // most testing frameworks provides Assert functionality
Assert.IsTrue(result.Count == 0);
Assert.IsFalse(String.IsNullOrEmpty(error));
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With