Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MOQ - setting up a method based on argument values (multiple arguments)

I have an interface defined as

interface IMath
{
 AddNumbersBetween(int lowerVal, int upperVal);
}

I can setup a basic Moq for the above as follows:

Mock<IMath> mock = new Mock<IMath>();    
mock.Setup(m => m.AddNumbersBetween(It.IsAny<int>(), It.IsAny<int>()));

call it

mock.Object.AddNumbersBetween(1,4);

and then verify that it was called

mock.Verify(m => m.AddNumbersBetween(1,4), Times.AtleastOnce());

I cant figure out how to setup the method AddNumbersBetween such that if the upperVal is lower than the lowerVal an exception is thrown

mock.Object.AddNumbersBetween(4,1);//should throw an exception

Essentially looking for something like:

mock.Setup(foo => foo.AddNumbersBetween("arg1 is higher than arg2")).Throws<ArgumentException>();
like image 238
Raj Rao Avatar asked Nov 02 '10 18:11

Raj Rao


People also ask

How do you do Moq method?

You can use Moq to create mock objects that simulate or mimic a real object. Moq can be used to mock both classes and interfaces. However, there are a few limitations you should be aware of. The classes to be mocked can't be static or sealed, and the method being mocked should be marked as virtual.

What does Moq setup do?

Moq provides a library that makes it simple to set up, test, and verify mocks. We can start by creating an instance of the class we're testing, along with a mock of an interface we want to use.

How do you mock a method in C#?

Trying to mock a method that is called within another method. // code part public virtual bool hello(string name, int age) { string lastName = GetLastName(); } public virtual string GetLastName() { return "xxx"; } // unit test part Mock<Program> p = new Mock<Program>(); p. Setup(x => x. GetLastName()).

What can be mocked with Moq?

Unit testing is a powerful way to ensure that your code works as intended. It's a great way to combat the common “works on my machine” problem. Using Moq, you can mock out dependencies and make sure that you are testing the code in isolation.


2 Answers

I know this is a year old, but I found a way to use multiple parameters with the latest version of Moq at least:

mock.Setup(x => x.Method(It.IsAny<int>(), It.IsAny<int>()))
    .Returns<int, int>((a, b) => a < b);
like image 185
Gustyn Avatar answered Oct 16 '22 21:10

Gustyn


For single argument methods, the cleanest way would be:

mock.Setup(foo => foo.Submit(IsLarge())).Throws<ArgumentException>();
...
public string IsLarge() 
{ 
  return Match<string>.Create(s => !String.IsNullOrEmpty(s) && s.Length > 100);
}

This can't be applied if the method has several arguments. There is still a 'workaround' that could be used, that mimics what you want to achieve:

/// <summary>
/// Tests if a moq can send an exception with argument checking
///</summary>
[TestMethod]
public void TestException()
{
    Mock<IMath> mock = new Mock<IMath>();
    mock.Setup(m => m.AddNumbersBetween(It.IsAny<int>(), It.IsAny<int>()));

    mock.Setup(foo => foo.AddNumbersBetween(It.IsAny<int>(), It.IsAny<int>()))
        .Callback<int, int>((i, j) => CheckArgs(i, j));

    try
    {
        mock.Object.AddNumbersBetween(1, 2);
    }
    catch (Exception ex)
    {
        // Will not enter
        Console.WriteLine("Exception raised: {0}", ex);
    }
    try
    {
        mock.Object.AddNumbersBetween(2, 1);
    }
    catch (Exception ex)
    {
        // Will enter here, exception raised
        Console.WriteLine("Exception raised: {0}", ex);
    }
}

private bool CheckArgs(int i, int j)
{
    if( i > j)
        throw new ArgumentException();
    return true;
}
like image 20
srodriguez Avatar answered Oct 16 '22 21:10

srodriguez