Autofixture: NSubstitute.ReceivedCalls() AutoFixture.AutoNSubstitute рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрд▓рдд рдорд╛рди рд▓реМрдЯрд╛ рд░рд╣рд╛ рд╣реИ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 28 рдорд╛рд░реНрдЪ 2018  ┬╖  10рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: AutoFixture/AutoFixture

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 'Class.ReceivedCalls ()' рдФрд░ 'var tmp = Class.Received(int).Property;' рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВред рдХреЙрд▓ рдЧрд┐рдирддреА рдХреА рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред AutoFixture рдХреЗ v3 рдореЗрдВ рдпрд╣ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рдХреЙрд▓ рдЧрдгрдирд╛ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдЧреБрдгреЛрдВ рдХреА, рдЬреЛ рдЕрдм рдпрд╣ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рддрд░реАрдХреЛрдВ рдХреА рдХреЙрд▓ рдЧрд┐рдирддреА рдЕрднреА рднреА рдареАрдХ рд▓рдЧрддреА рд╣реИред
рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рд╣реИ:

    public interface IRunSpeed
    {
        int Speed { get; }
    }

    public class GetToDaChoppa
    {
        private readonly IRunSpeed _runSpeed;

        public GetToDaChoppa(IRunSpeed runSpeed)
        {
            _runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
        }

        public void DoItNow()
        {
            var runningSpeed = _runSpeed.Speed;
        }
    }

рдФрд░ рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ:

        [Fact]
        public void DoItNow_WithOutAutoNSubstitute()
        {
            // Arrange
            var runSpeed = Substitute.For<IRunSpeed>();
            runSpeed.Speed.Returns(2);

            var sut = new GetToDaChoppa(runSpeed);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Single(runSpeed.ReceivedCalls());
        }

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Single(runSpeed.ReceivedCalls());

рдореЗрд░рд╛ AutoNSubstituteDataAttribute рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

        public class AutoNSubstituteDataAttribute : AutoDataAttribute
        {
            public AutoNSubstituteDataAttribute()
                : base(() => new Fixture()
                           .Customize(new AutoNSubstituteCustomization()))
            {
            }
        }

рдкрд╣рд▓рд╛ рдкрд░реАрдХреНрд╖рдг 'DoItNow_WithOutAutoNSubstitute' рдареАрдХ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИред рд▓реЗрдХрд┐рди рджреВрд╕рд░рд╛ рдкрд░реАрдХреНрд╖рдг 'DoItNow_UsingAutoNSubstitute' 'ios.Received(1).Speed;' рдХреЗ рд▓рд┐рдП 2 рджреЗрддрд╛ рд╣реИред
рдпрд╣ 'runSpeed.ReceivedCalls();' рдХреЗ рд▓рд┐рдП рднреА 2 рджреЗрддрд╛ рд╣реИред
рдЗрд╕ рд╡рдЬрд╣ рд╕реЗ рд╣рдо рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЛ v4 рдореЗрдВ рдЕрдкрдЧреНрд░реЗрдб рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреБрд░рдВрдд> рдкреНрд░рддрд┐ рд╕рдорд╛рдзрд╛рди 1000 рд╡рд┐рдлрд▓ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВред рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ рдпрд╛ рдлрд┐рдХреНрд╕ рдХрд╣рд╛рдВ рджреЗрдЦрдирд╛ рд╣реИ, рдЗрд╕ рдкрд░ рдХреЛрдИ рдорд╛рд░реНрдЧрджрд░реНрд╢рди?

рд╕рднреА 10 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдореБрджреНрджрд╛ рдЙрдард╛рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рджрд░рдЕрд╕рд▓, рдЗрд╕ рдореБрджреНрджреЗ рдХрд╛ рдСрдЯреЛрдлрд┐рдХреНрдЪрд░ рд╕реЗ рдХреЛрдИ рд▓реЗрдирд╛-рджреЗрдирд╛ рдирд╣реАрдВ рд╣реИ, рдЬрдмрдХрд┐ рд╣рдо рднреА рдЗрд╕рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ

рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдЬреНрдпрд╛рджрд╛рддрд░ xUnit рдХреЗ рдХрд╛рд░рдг рд╣реЛрддреА рд╣реИ рдФрд░ рдпрджрд┐ рдЖрдк рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд░реВрдк рдореЗрдВ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдкрд╛рд╕ рд╣реЛ рдЬрд╛рдПрдЧрд╛:
```рд╕реА#
[рд╕рд┐рджреНрдзрд╛рдВрдд, AutoNSubstituteData]
рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╢реВрдиреНрдп DoItNow_UsingAutoNSubstitute_CreateManually(IFixture рд╕реНрдерд┐рд░рддрд╛)
{
// рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░реЗрдВ
рд╡рд░ рд░рдирд╕реНрдкреАрдб = рдлрд┐рдХреНрд╕реНрдЪрд░ред рдлреНрд░реАрдЬ();
рд╡рд░ рд╕реБрдд = рд╕реНрдерд┐рд░рддрд╛ред рдмрдирд╛рдПрдБ();
рд░рдирд╕реНрдкреАрдбредрд╕реНрдкреАрдбредрд░рд┐рдЯрд░реНрдиреНрд╕ (49);

//Act
sut.DoItNow();

//Assert
var tmp = runSpeed.Received(1).Speed;
Assert.Single(runSpeed.ReceivedCalls());

}
```

рдЬрдм рдЖрдк рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ xUnit рдЖрдкрдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдирд╛рдо рдХреЛ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдпрд╣ рдкрд╛рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд░ рдЬреНрдЮрд╛рдд рдирд╣реАрдВ рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ ToString() рдЕрдзрд┐рднрд╛рд░ рдирд╣реАрдВ рд╣реИ, рддреЛ рдпрд╣ рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдирд┐рд░реАрдХреНрд╖рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╕рдВрдкрддреНрддрд┐ рдореВрд▓реНрдпреЛрдВ рдХреЛ рджреЛрдмрд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рдкрд░реАрдХреНрд╖рдг рдХреЗ рдирд╛рдо рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджрд┐рдЦрд╛рдИ рджреЗрдВрдЧреЗ:
image

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, xUnit рдиреЗ рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдг рддрд░реНрдХ рдХреЛ рдЕрдЪреНрдЫреА рддрд░рд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП Speed рд╕рдВрдкрддреНрддрд┐ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ред рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЖрд╣реНрд╡рд╛рди рд╣реИ, NSubstitute рдиреЗ рдЗрд╕реЗ рдПрдХ рдХреЙрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЧрд┐рдирд╛ред

рдпрд╣ рдХрд╛рдлреА рдЕрдЬреАрдм рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ v3 рдХреЗ рд╕рд╛рде рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рдереА, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рд╕рдВрдмрдВрдз рдореЗрдВ рдХреБрдЫ рднреА рдирд╣реАрдВ рдмрджрд▓рд╛ред рдореИрдВрдиреЗ рдЕрднреА xUnit2 + AutoFixture v3 рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЕрднреА рднреА рд╕рдорд╕реНрдпрд╛ рдорд┐рд▓реА рд╣реИред рд╢рд╛рдпрдж, рдЖрдкрдиреЗ xUnit рдХреЛ рднреА рдЕрдкрдЧреНрд░реЗрдб рдХрд┐рдпрд╛ рд╣реИред


рд╡рд░реНрдХрдЕрд░рд╛рдЙрдВрдб рдХреЗ рд▓рд┐рдП, рдореЗрд░реЗ рдкрд╛рд╕ рдЕрдЪреНрдЫреА рдФрд░ рдмреБрд░реА рдЦрдмрд░реЗрдВ рд╣реИрдВред рдЕрдЪреНрдЫреА рдЦрдмрд░ рдпрд╣ рд╣реИ рдХрд┐ рдЗрд╕реЗ NSubsitute рдХреЗ рдЕрдЧрд▓реЗ рдкреНрд░рдореБрдЦ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдиреЗ рдкреНрд░реЙрдХреНрд╕реА рдЖрдИрдбреА рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП ToString() рдкрджреНрдзрддрд┐ рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджрд┐рдпрд╛ рдерд╛ред рдирддреАрдЬрддрди, xUnit рдЕрдм рдЧреБрдгреЛрдВ рдХреЛ рдирд╣реАрдВ рдЫреВрддрд╛ рд╣реИ:
image

рдмреБрд░реА рдЦрдмрд░ рдпрд╣ рд╣реИ рдХрд┐ NSubsitute v4 рдЕрднреА рддрдХ рдЬрд╛рд░реА рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдореИрдВ рдЖрдкрдХреЛ рдпрд╛ рддреЛ рд╕реБрдЭрд╛рд╡ рджреЗ рд╕рдХрддрд╛ рд╣реВрдВ:

  • NSubsitute v4 рдЬрд╛рд░реА рд╣реЛрдиреЗ рддрдХ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рд╕реНрдердЧрд┐рдд рдХрд░реЗрдВ;
  • NSubsitute рдХреЗ рдирд╡реАрдирддрдо master рд╕реНрд░реЛрдд рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рдПрдХ рд╕реНрдерд╛рдиреАрдп рдирд┐рд░реНрдорд╛рдг рдХрд░реЗрдВ рдФрд░ NuGet рдкреИрдХреЗрдЬ рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ NSubsitute.dll рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред v4 рдЬрд╛рд░реА рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк NuGet рдкреИрдХреЗрдЬ рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
  • рдпрджрд┐ рдЖрдкрдиреЗ xUnit рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рднреА рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рд╣реИ (рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╕рдордЭрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рдпрд╣ рд╕рдорд╕реНрдпрд╛ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдереА), рдЙрд╕ рдкрд░рд┐рд╡рд░реНрддрди рдХреЛ рд╡рд╛рдкрд╕ рд▓рд╛рдПрдВ рдФрд░ xUnit рдХреЗ рдкрд┐рдЫрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рдЕрд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП рдореБрдЭреЗ рдЦреЗрдж рд╣реИ, рд▓реЗрдХрд┐рди, рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдо рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП AutoFixture рдХреА рдУрд░ рд╕реЗ рдХреБрдЫ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред

рдмрд╕ рдЗрд╕рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ред рдЕрдВрдд рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рд░рд┐рд╕реАрд╡реНрдб рдХреЙрд▓реНрд╕ рдкрд░ рдЬреЛрд░ рджреЗрддреЗ рд╣реБрдП рдлрд┐рд░ рд╕реЗ рдПрдХ рд╕рдлрд▓ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рдкрд╕ рдЪрд▓реЗ рдЧрдПред
рдХреБрдЫ рдРрд╕рд╛ рдЬреЛ рдЕрднреА рднреА рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ, рд╡рд╣ рд╣реИ рд░рд┐рд╕реАрд╡реНрдб (рдПрдХреНрд╕) рдЬреИрд╕реЗ рд░рд┐рд╕реАрд╡реНрдб (1)ред рд╕реНрдкреАрдб рдбреЗрдирд┐рдпрд▓ рдЬреИрд╕рд╛ рдКрдкрд░ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред

snip_20180328181559

рдХреНрдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рднреА рд╣реИрдЯ рдХрд╛ рдЬрд╡рд╛рдм/рд╕рдорд╛рдзрд╛рди рд╣реИ?

рдХреНрдпрд╛ рдЖрдк рд▓реЛрдЧ рдПрдХ рд╣реА рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ? :) рдпрджрд┐ рд╣рд╛рдВ, рддреЛ рдХреНрдпрд╛ рдЖрдк рд╕реНрдкрд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдиреЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдХреИрд╕реЗ рдХрд┐рдпрд╛?

рдКрдкрд░ рд╕реБрдЭрд╛рдП рдЧрдП рд╡рд┐рдХрд▓реНрдкреЛрдВ рд╕реЗ рджреЛрдиреЛрдВ рдореБрджреНрджреЛрдВ рдореЗрдВ рдорджрдж рдорд┐рд▓рдиреА рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рд╡реЗ рдирд╣реАрдВ - рдкрд░рд┐рджреГрд╢реНрдп рд╕реНрдкрд╖реНрдЯ рдХрд░реЗрдВред

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╣реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд╣реАрдВ рдмрд▓реНрдХрд┐ рдПрдХ рд╣реА рдХрдВрдкрдиреА рдореЗрдВред
рд╣рдо рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ xunit 1.9 + nsubstitute 2/3 рдкрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рдЗрд╕реЗ рдЕрдкрдиреА рдЖрдВрддрд░рд┐рдХ рдЕрд╕реЗрдВрдмрд▓реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдмрдВрдзрд┐рдд рдХрд┐рдпрд╛ рд╣реИ (рдирдЧреЗрдЯ рдкреИрдХреЗрдЬ рдЗрд╕рд▓рд┐рдП рдХреЗрд╡рд▓ рдПрдХ рд╕рдВрджрд░реНрдн рдХреЗ рдкреБрд░рд╛рдиреЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдПрдХ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдЙрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ рдЬрд┐рддрдирд╛ рд▓рдЧрддрд╛ рд╣реИред рд╣реЛрдирд╛) xunit2 рдХреЗ рдЕрдиреБрдХреВрд▓ рд╣реЛрдирд╛ред рдФрд░ рдЕрдм рд╣рдореЗрдВ рдпреЗ рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВред

рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╣реА рдХреБрдЫ рдЪреАрдЬреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдЕрдВрдд рдореЗрдВ рд╕реЛрдЪрд╛ рдХрд┐ рдЗрд╕рдХрд╛ рдСрдЯреЛрдлрд┐рдХреНрд╕реНрдЪрд░ рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ - рдЬрдореЗ рд╣реБрдП-рд╡рд┐рд╢реЗрд╖рддрд╛ рдФрд░ рд╣рд╛рд░реНрдб рдХреЛрдбрд┐рдд рдкрд░реАрдХреНрд╖рдг рдирд┐рд╖реНрдкрд╛рджрди рдЧрдгрдирд╛ рдХреЗ рдХрд╛рд░рдг - рдпрд╛ рдРрд╕рд╛ рдХреБрдЫред
рдбреЗрдирд┐рдпрд▓ рджреНрд╡рд╛рд░рд╛ рдЗрд╕ рдХреЗрд╕ рдХреЛ рдЦреЛрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЙрдиреНрд╣реЛрдВрдиреЗ рдореБрдЭреЗ рдЗрд╕рдХрд╛ рд▓рд┐рдВрдХ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ред

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдкрдиреЗ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рд╣реИ, рдореИрдВрдиреЗ nuget 3.1 рд╕рдВрджрд░реНрдн рдХреЛ рддрд╛рдЬрд╝рд╛ рд╕рдВрдХрд▓рд┐рдд nsubstitute рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╕реЗ рдмрджрд▓ рджрд┐рдпрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж рдЕрдм рдореЗрд░реЗ рдкрд╛рд╕ 178 рдЕрд╕рдлрд▓ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдмрдЬрд╛рдп 118 рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ Receiced(x) рдЕрднреА рднреА рдХреЙрд▓ рдХреА рдЧрд▓рдд рд╕рдВрдЦреНрдпрд╛ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░ рд░рд╣рд╛ рд╣реИред

рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╡рд░реНрддрдорд╛рди рдореЗрдВ xunit2 рдХреЗ рд╕рд╛рде .net 4.5.2 рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, nsubstitute рдХрд╛ рд╡рд░реНрддрдорд╛рди рд░реЗрдкреЛ рд╕рдВрд╕реНрдХрд░рдг рдФрд░ рдСрдЯреЛрдлрд┐рдХреНрд╕реНрдЪрд░ 4.2 рд╕рдВрджрд░реНрднрд┐рдд рд╣реИред рд╕рднреА рдкрд░реАрдХреНрд╖рдг рдПрдХ рд╣реА рджреЛ рдХрд╛рд░рдгреЛрдВ рд╕реЗ рд╡рд┐рдлрд▓ рд╣реЛ рд░рд╣реЗ рд╣реИрдВ - рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдЕрднреА рднреА рдХреБрдЫ рдкреНрд░рд╛рдкреНрдд рдХреЙрд▓ рд╡рд┐рдлрд▓ рд╣реЛ рд░рд╣реЗ рд╣реИрдВред
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЬрдм рдореИрдВ рдлрд┐рд░ рд╕реЗ рдХрд╛рд░реНрдпрд╛рд▓рдп рдореЗрдВ рд╡рд╛рдкрд╕ рдЖрдКрдВрдЧрд╛ (рдИрд╕реНрдЯрд░ рдХреЗ рд▓рд┐рдП рдмрд╛рд╣рд░) рддреЛ рдореБрдЭреЗ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдЧрд╣рд░рд╛рдИ рд╕реЗ рджреЗрдЦрдирд╛ рд╣реЛрдЧрд╛ред
рд╢рд╛рдпрдж @dklinger рдЗрд╕ рдмреАрдЪ рдкрд░рд┐рджреГрд╢реНрдп рдХрд╛ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред

@dklinger @evilbaschdi рдХреГрдкрдпрд╛ рдЗрд╕реЗ рдЬрд╛рдВрдЪрдиреЗ рдХрд╛ рдореМрдХрд╛ рдорд┐рд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЕрдиреБрд╡рд░реНрддреА

рдпрд╣ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрднреА рднреА рдЬрд╛рдВрдЪ рдЬрд╛рд░реА рд╣реИред

рдареАрдХ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рдШрдВрдЯреЛрдВ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред рдкрд╣рд▓рд╛: рдЖрдкрдХреЗ рдЙрддреНрддрд░, рдЖрдкрдХреЗ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдФрд░ рд╕реБрдЭрд╛рд╡реЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж - рдЗрд╕рд╕реЗ рдмрд╣реБрдд рдорджрдж рдорд┐рд▓реАред
рдореИрдВрдиреЗ NSubstitute рдХреЗ v4 рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рд╣реИред рдпрд╣ рдЙрдкрд░реЛрдХреНрдд рдореЗрд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдореБрджреНрджрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдЧрд▓рдд рд░рд┐рд╕реАрд╡реНрдб рдХреЙрд▓реНрд╕-рдХрд╛рдЙрдВрдЯ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рддрд╛ рд╣реИ, рдХреЗрд╡рд▓ рдПрд╕рдпреВрдЯреА-рдХреЙрд▓ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП, рдЧреБрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред

рд╣рдорд╛рд░реЗ рдЕрдм рдХрд╛рдо рдХрд░ рд░рд╣реЗ рдХреЛрдб рдХрд╛ рдЙрджрд╛рд╣рд░рдг:

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            sut.DoItNow();

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдореИрдВ "GetToDaChoppa.DoItNow ();" рд╡рд┐рдзрд┐ рдмрджрд▓рддрд╛ рд╣реВрдВ рдПрдХ рд╕рдВрдкрддреНрддрд┐ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП "GetToDaChoppa.DoItNow" рдкреНрд░рд╛рдкреНрдд рдХреЙрд▓реНрд╕рдХрд╛рдЙрдВрдЯ рдлрд┐рд░ рд╕реЗ +1 рд╣реИ:

        [Theory, AutoNSubstituteData]
        public void DoItNow_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            var x = sut.DoItNow;

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ xUnit рдирд╛рдордХрд░рдг рдХреЗ рд╕рд╛рде рдХрд░рдирд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдпрд╣ рдХрд╛рд░реНрдп рдкрджреНрдзрддрд┐-рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдорд┐рд▓рддрд╛ рд╣реИ:
image

рдФрд░ рд╡рд╣ рдПрдХ рдЧреИрд░-рдХрд╛рд░реНрдпрд╢реАрд▓ рд╕рдВрдкрддреНрддрд┐-рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП:
image

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ xUnit рдкрд░реАрдХреНрд╖рдг-рдирд╛рдо рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдореВрд▓реНрдп рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд╕рдпреВрдЯреА-рд╕рдВрдкрддреНрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░ рд░рд╣рд╛ рд╣реИ рд▓реЗрдХрд┐рди рдпрд╣ рдПрд╕рдпреВрдЯреА-рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред рдореЗрд░рд╛ рдкрд╣рд▓рд╛ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рдерд╛ рдХрд┐ рдЗрд╕реЗ рд╣рдорд╛рд░реА рд╡рд┐рдзрд┐ "GetToDaChoppa ()" рдХреЗ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХреЗ рд╕рд╛рде рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд╢реВрдиреНрдп рдерд╛ред рд▓реЗрдХрд┐рди рдЗрд╕реЗ "рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ int GetToDaChoppa ()" рдХреЗ рд░реВрдк рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж рднреА xUnit рдЕрднреА рднреА рдкрд░реАрдХреНрд╖рдг рдирд╛рдо рдХреЗ рд▓рд┐рдП рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдХреЙрд▓ рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИред рдЧреБрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИред

рдЕрднреА рдХреЗ рд▓рд┐рдП рдореИрдВ рдлрд┐рд░ рд╕реЗ рдлрдВрд╕ рдЧрдпрд╛ рд╣реВрдБред рдореИрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣рдордд рд╣реВрдВ рдХрд┐ рдпрд╣ рдСрдЯреЛрдлрд┐рдХреНрдЪрд░ рдХрд╛ рдореБрджреНрджрд╛ рдирд╣реАрдВ рд╣реИред рд▓реЗрдХрд┐рди рдЖрдкрдХреА рд░рд╛рдп рдореЗрдВ, рд╕рднреА рдкреИрдХреЗрдЯреЛрдВ рдХреЛ рд╣рдорд╕реЗ рдмреЗрд╣рддрд░ рдЬрд╛рдирдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХрд╛ рдХреНрдпрд╛ рд╕реБрдЭрд╛рд╡ рд╣реЛрдЧрд╛?

  • NSubstitute рдХреЗ рд▓рд┐рдП рдПрдХ рдореБрджреНрджрд╛ рдЦреЛрд▓рдирд╛?
  • xUnit2 рдХреЗ рд▓рд┐рдП рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рдЦреЛрд▓рдирд╛?
  • рдпрд╛ рдХреБрдЫ рдмрд┐рд▓реНрдХреБрд▓ рдирдпрд╛?

@dklinger рдлреЙрд▓реЛ-рдЕрдк рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж! рдХреНрдпрд╛ рдЖрдк рдХреГрдкрдпрд╛ рдЕрдВрддрд┐рдо рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдХреЛрдб рдХрд╛ MCVE рд╕рд╛рдЭрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЕрднреА рднреА рд╡рд┐рдлрд▓ рд╣реИ? рдмрд╕ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдХреБрдЫ рднреА рдЫреВрдЯ рди рдЬрд╛рдП рдФрд░ рдореИрдВрдиреЗ рд╢рд░реНрддреЛрдВ рдХреЛ рдЧрд▓рдд рдирд╣реАрдВ рд╕рдордЭрд╛ред

рдЙрд╕рдХреЗ рдмрд╛рдж рдореИрдВ рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рдРрд╕рд╛ рдХреНрдпреЛрдВ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдПред

рдзрдиреНрдпрд╡рд╛рджред

рд╣рд╛рдБ, рдЬрд╝рд░реВрд░ред рдпрд╣ рд░рд╣рд╛:

рдкрд░реАрдХреНрд╖рдг рдХреЗ рддрд╣рдд рдкреНрд░рдгрд╛рд▓реА:

    public interface IRunSpeed
    {
        int Speed { get; }
        void Dude();
        int Dude2();
    }

    public class GetToDaChoppa
    {
        private readonly IRunSpeed _runSpeed;

        public GetToDaChoppa(IRunSpeed runSpeed)
        {
            _runSpeed = runSpeed ?? throw new ArgumentNullException(nameof(runSpeed));
        }

        public int DoItNow
        {
            get
            {
                var runningSpeed = _runSpeed.Speed;
                return 0;
            }
        }
    }

рдкрд░реАрдХреНрд╖рдг рдХрд╛ рдорд╛рдорд▓рд╛:

        [Theory, AutoNSubstituteData]
        public void DoItNowAsProperty_UsingAutoNSubstitute(
            [Frozen] IRunSpeed runSpeed,
            GetToDaChoppa sut)
        {
            // Arrange
            runSpeed.Speed.Returns(49);

            //Act
            var x = sut.DoItNow;

            //Assert
            var tmp = runSpeed.Received(1).Speed;
            Assert.Equal(1, runSpeed.ReceivedCalls().Count());
        }

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рдореИрдВ https://github.com/xunit/xunit/issues/1386 рдФрд░ https://github.com/AutoFixture/AutoFixture/issues/805 рдкрд░ рдЪрд░реНрдЪрд╛рдУрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ
рдореИрдВрдиреЗ рдбрд┐рд╕реНрдкреНрд▓реЗрдирд╛рдо рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рддреЗ рд╣реБрдП рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдереНрдпреЛрд░реА рдПрдЯреНрд░рд┐рдмреНрдпреВрдЯ рдмрдирд╛рдиреЗ рдХреА рднреА рдХреЛрд╢рд┐рд╢ рдХреА, рд▓реЗрдХрд┐рди рдпрд╣ рдпрд╛ рддреЛ рдорджрдж рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ xUnit рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдЕрднреА рднреА рдЖрдВрддрд░рд┐рдХ рд░реВрдк рд╕реЗ рдСрдЯреЛрдЬреЗрдирд░реЗрдЯреЗрдб рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИред рд▓реЗрдХрд┐рди рдпрд╣ рд╕рд┐рд░реНрдл fyi рд╣реИ рдФрд░ рдЙрдкрд░реЛрдХреНрдд рдбреЗрдореЛ-рдХреЛрдб рд╕реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд╕рдВрдмрдВрдзрд┐рдд рд╣реИред

        public sealed class MyTheoryAttribute : TheoryAttribute
        {
            public MyTheoryAttribute([CallerMemberName] string memberName = null)
            {
                DisplayName = "MyTestCase";
            }
        }

image

рд╣реИрд▓реЛ, рдореБрдЭреЗ рдлрд┐рд░ рд╕реЗ :)
рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ xUnit2 рдкрд░реАрдХреНрд╖рдг-рд╡рд┐рдзрд┐-рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рднреА рдЧреБрдгреЛрдВ рдФрд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдмреБрд▓рд╛ рд░рд╣рд╛ рд╣реИ рдЬреЛ рдПрдХ рдЬрдЯрд┐рд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВред рдХреЛрдб рдХреА рд▓рд╛рдЗрди рдпрд╣ рд╣реИ: https://github.com/xunit/assert.xunit/blob/2b70a9b0c5bb291f98472ec24cec437acf8d65c8/Sdk/ArgumentFormatter.cs#L156

рдЖрдкрдХреЗ рд╕рдорд░реНрдерди рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВрдиреЗ xUnit-Repo рдкрд░ рдПрдХ рдореБрджреНрджреЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓ рджрд┐рдпрд╛ рд╣реИ рдЬрд╣рд╛рдБ рдЪрд░реНрдЪрд╛ рдЬрд╛рд░реА рд░рд╣рдиреА рдЪрд╛рд╣рд┐рдП: https://github.com/xunit/xunit/issues/1682

@dklinger рд╡рд┐рд╕реНрддреГрдд рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рдлреА рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдФрд░ рдХрд┐рд╕реА рддрд░рд╣ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИред AutoFixture рдФрд░ NSubsitute рдХреЗ рдирдЬрд░рд┐рдП рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдХреЛрдб рдХреЛ рдХрд╣реАрдВ рдЧрд╣рд░рд╛рдИ рд╕реЗ xUnit рдпрд╛ рдЯреЗрд╕реНрдЯ рдмреЙрдбреА рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрд╛ рдирд╣реАрдВред

рдЖрдорддреМрд░ рдкрд░, рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣рд▓ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрдк NSubstitute рдХреА рд╕реНрдкрд╖реНрдЯ рд╕реБрд╡рд┐рдзрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

runSpeed.ClearReceivedCalls();

рдпрд╣ рдХреЛрдб рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛ рдореЗрдВ рдЪрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬрд╣рд╛рдВ рдЖрдк рдХреЙрд▓ рдХреА рд╕рдЯреАрдХ рд╕рдВрдЦреНрдпрд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреБрдЫ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ рддреЛ рдпрд╣ рдареАрдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдпрджрд┐ рд╣рдЬрд╛рд░реЛрдВ рдкрд░реАрдХреНрд╖рдг рдкреНрд░рднрд╛рд╡рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдмрд╣реБрдд рдорджрдж рдирд╣реАрдВ рдХрд░реЗрдЧрд╛

рдпрд╣ рдЕрдлрд╝рд╕реЛрд╕ рдХреА рдмрд╛рдд рд╣реИ рдХрд┐ NSubsitute + xUnit2 + AutoFixture рдПрдХреАрдХрд░рдг рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдореБрджреНрджреЛрдВ рд╕реЗ рдЧреНрд░рд╕реНрдд рд╣реИред AutoFixture рдЙрддреНрдкрд╛рдж рдХреЛ рдЬреАрд╡рди рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рди рдХрд┐ рдЗрд╕реЗ рдПрдХ рдмреБрд░рд╛ рд╕рдкрдирд╛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╢рд╛ рд╣реИ рдХрд┐ xUnit рдХреЗ рд▓реЛрдЧ рдЖрдкрдХреЛ рдкреВрд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддреНрд╡рд░рд┐рдд рддрд░реАрдХрд╛ рд╕реБрдЭрд╛рдПрдВрдЧреЗред

рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдо рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕реБрдзрд╛рд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдУрд░ рд╕реЗ рдХреБрдЫ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕