Jau kelis metus Moq yra populiariausias netikrų objektų kūrimo karkasas .NET pasaulyje. Moq labai praverčia testavime, kai norima aprašyti netikrą objektą, kuris tenkina tam tikrą interfeisą. Tarkime, mes turime klasę FileSystem, kuri yra ne kas kitas, kaip failų sistemos abstrakciją bei klasę FileFinder, skirtą failų paieškai:

public class FileFinder
{
    private readonly IFileSystem fileSystem;

    public FileFinder()
        : this(new FileSystem())
    {
    }

    public FileFinder(IFileSystem fileSystem)
    {
        this.fileSystem = fileSystem;
    }

    public IEnumerable<string> Find(string dir, string filter, bool recursively = true)
    {
        var options = recursively ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
        return this.fileSystem.GetDirectoryFiles(dir, filter, options);
    }
}

public interface IFileSystem
{
    IEnumerable<string> GetDirectoryFiles(string dir, string filter, SearchOption options);
}

public class FileSystem : IFileSystem
{
    public IEnumerable<string> GetDirectoryFiles(string dir, string filter, SearchOption options)
    {
        return Directory.GetFiles(dir, filter, options);
    }
}

Pagal visas modulių testų rašymo taisykles, FileFinder derėtų testuoti ne su tikra failų sistemą, bet su menama. Moq pagalba tai atrodytų taip:

[Test]
public void Moq_Example()
{
    var fileSystem = new Mock<IFileSystem>();
    fileSystem
        .Setup(fs => fs.GetDirectoryFiles(It.IsAny<string>(), "*.csv", SearchOption.AllDirectories))
        .Returns(new[] { "aaa.csv", "bbb.csv", "ccc.csv" });

    var fileFinder = new FileFinder(fileSystem.Object);

    var files = fileFinder.Find("mydir", "*.csv");

    fileSystem.Verify(
        fs => fs.GetDirectoryFiles("mydir", "*.csv", SearchOption.AllDirectories), Times.Once());

    CollectionAssert.IsNotEmpty(files);
}

Pavyzdyje pirma aprašoma kaip objektas fileSystem turi reaguoti į GetDirectoryFiles metodo iškvietimą su tam tikrais parametrais, tada iškviečiamas fileFinder metodas Find ir tikrinama, ar GetDirectoryFiles buvo iškviestas lygiai vieną kartą su teisingais argumentais.

Prieš kurį laiką .NET horizonte atsirado naujas Moq konkurentas – NSubstitute. Iš funkcionalumo pusės abu karkasai panašūs, bet NSubstitute turi vieną privalumą – daug aiškesnį API lyginant su Moq. Anksčiau pateiktas pavyzdys perrašytas su NSubstitute pateiktas žemiau:

[Test]
public void NSubstitute_Example()
{
    var fileSystem = Substitute.For<IFileSystem>();
    fileSystem
        .GetDirectoryFiles(Arg.Any<string>(), "*.csv", SearchOption.AllDirectories)
        .Returns(new[] { "aaa.csv", "bbb.csv", "ccc.csv" });

    var fileFinder = new FileFinder(fileSystem);

    var files = fileFinder.Find("mydir", "*.csv");

    fileSystem.Received(1).GetDirectoryFiles("mydir", "*.csv", SearchOption.AllDirectories);

    CollectionAssert.IsNotEmpty(files);
}

NSubstitute dar yra palyginamai jaunas projektas, tad pasitaiko ir tam tikrų klaidų. Nepaisant to, kasdieniniame darbe pastebiu save vis dažniau ir dažniau naudojant NSubstitute vietoje Moq.

P.S.

Jeigu jau esate naudoję NSubstitute, būtų šaunu komentaruose išgirsti jūsų patirtį!

Patiko (0)

Rodyk draugams