Lets say we have the following interface:
public interface IGetRandomString
{
void Init();
bool IsInited { get; }
//returns random string of length chars
string GetRandomString(int length);
}
and a mock for it described in a classic way:
public void GetRandomStringTest()
{
private bool initialized;
private Random random = new Random();
private string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-._";
private Mock<IGetRandomString> mock;
private IGetRandomString mockedInterface;
//mock setup
mock = new Mock<IGetRandomString>();
mockedInterface = mock.Object;
mock.Setup(d => d.Init()).Callback(() => initialized = true);
mock.Setup(d => d.IsInited).Returns(() => initialized);
mock.Setup(d => d.GetString(It.IsAny<int>())).Returns<int>(length => initialized ? GetRandomString(length) : string.Empty);
//unit test
const int length = 10;
mockedInterface.Init();
var isInited = mockedInterface.IsInited;
var ret = mockedInterface.GetString(length);
Assert.That(ret.Length == length);
}
private string GetRandomString(int length) => new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
How to get the same setup with modern Mock.Of<T> syntax?
...
mockedInterface = Mock.Of<IGetRandomString>(m =>
//property setup is ok
m.IsInited == initialized &&
//how to setup action method and it's callback?
m.Init() &&
//how to capture length method parameter?
m.GetString(It.IsAny<int>()) == (initialized ? GetRandomString(length) : string.Empty));
mock = Mock.Get(IGetRandomString);
...