nick_green
nick_green

Reputation: 1664

Unit test doesn't work because of void method

I have to write a unit test for some methods and I reached a method that returns void:

public virtual void ReadCities(string filename)
{
      var engine = new FileHelperEngine(typeof (GeoDbCity));
      _geoDbCities = engine.ReadFile(filename) as GeoDbCity[];
}

And my test method is:

[Test]
public void CheckIfCitiesWereRead()
{
    var getGeoDbCitiesMock = new Moq.Mock<GeoDbReader>();
    getGeoDbCitiesMock.Setup(y => y.ReadCities("ConstCities.csv"));
    Assert.NotNull(getGeoDbCitiesMock.Object.ReadCities("ConstCities.csv"));
}

When assert is being called i'm getting an error:

Argument type 'void' is not assignable to parameter type 'object'.

My question is:

How to deal with void type methods and how test them? In this particular case how to test if ReadCities method actualy read something?

Upvotes: 0

Views: 387

Answers (3)

Jochen van Wylick
Jochen van Wylick

Reputation: 5401

You question actually consists of two questions: how to test void() methods, and how to test this ReadCities(string fileName) method.

In response to the first - In case your void method changes the internal state of the object, then that is what you can test for:

Example:

public class Person
{
    public int age;

    public void SetAge(int age)
    {
        this.age = age;
    }
}

Then your test would be

var p = new Person();
p.SetAge(12);
Assert.AreEqual(p.age, 12);

In response to the question how to test that ReadCities method, well, you don't want to Mock it for one. You only mock the stuff you don't want to test - in a test.

Add a CSV file to your testproject ( type = content, action = copy always ) and use the DeploymentItem attribute to copy the CSV file into the test folder. Then test with

var service = new Service();
service.ReadCities(pathToCsvFile);
Assert.NotNull(service.Cities);
// Actually - you want better assertions

So maybe ReadCities might be a void method, you can test the internal state of the object after, so the cities list. If you don't expose the list of cities, there's another thing called the InternalsVisibleToAttribute which allows your tests to access private members. However, then we can get into a discussion of whether private members need to be tested in the first place.

Upvotes: 1

Yogi
Yogi

Reputation: 11

In the strictest sense, if you ware testing only the ReadCities method, your mock shouldn't be testing that engine.ReadFile actually did something (you would have another unit test for that). You should isolate this method by mocking the call to engine.ReadFile (which I think you've done, but I'm not completely familiar with Moq).

In any case, what you'll likely need to do is create a public accessor for _geoDbCities that you can check in your Assert.

Upvotes: 0

Sebastian Negraszus
Sebastian Negraszus

Reputation: 12195

If a method does not return anything, then that method must have some side-effect such as changing a property of the class. Test that side-effect, e.g. test the value of said property.

Upvotes: 5

Related Questions