简体   繁体   中英

Unit testing 101 - throwing an exception from within my unit

I asked a related question. I want to give both those posters credit for the information that they provided based on my inadequate information in the post. They have lead me to this question here. If I can understand this, then off I go to credit the posters who have helped me thus far as well as any of you helpful folk.

I have an interface

public interface InventoryRepository
{


    List<Location> GetLocations();
    List<InventoryItem> GetItems();
    List<InventoryItem> GetItems(int LocationId);
    HomeMadeItem GetHomeMadeItem(int ItemId);
    StoreBoughtItem GetStoreBoughtItem(int ItemId);
    Location GetLocation(int LocationId);
    int SaveHomeMadeItem(HomeMadeItem item);
    string DeleteItem(int id);

}

My MVC app is going to be happy as a pig in ... well you know, so long as this contract is satisfied. Woot, all is good.

So you see, I have a DeleteItem method that is implemented thusly:

    public string DeleteItem(int ItemId)
    {

        using (var context = new InventoryEF())
        {
            var item = context.InventoryItems.Find(ItemId);
            if (item != null)
            {
                try
                {
                    context.InventoryItems.Remove(item);
                    context.SaveChanges();
                    return "";
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return e.InnerException.ToString();
                }
            }
            else
            {
                return "Id not found for delete";
            }
        }
    }

I can very easily devise a unit test that tests the return value on successful deletion or item not found. I do not know how to devise a unit test that demonstrates the correct return value for a thrown exception.

Moq was suggested. But my original question was not clear enough for me to be certain that this is the correct approach.

Does anyone have a suggestion as to how to devise this unit test?

using (var context = new InventoryEF())

That is a problem since you are instantiating a dependency directly. You need to make the context injectable somehow (which is a part of different discussion).

Once you have InventoryEF a dependency, you can mock any of the methods the context is using and then throw exception on it through the MOQ framework, to be able to test your exception handling.

something like this, please check the syntax:

var mockContext = new Mock<IInventoryEF>();
mockContext.Setup(c=>c.SaveChanges()).Throws<Exception>();

As pointed out in another reply, you should also have either the Attribute for ExpectedException or if you use FluentAssertions you can also expect exceptions inline .

If all you want is to catch a specific exception, and you aren't using MOQ already, I'd suggest the ExpectedExceptionAttribute :

[TestMethod]
[ExpectedException(typeof(IDNotFoundException))]
public void WhicheverTestMethod()
{
  ..
}

Where of course the type of exception can be whatever you want. I'm fairly sure you can check against the message as well.

In general, I'd also suggest not catching type Exception and getting the InnerException because there may be no inner exception, and you can't really test all possible exceptions because Exception is extendable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM