public void RunsBothBranchesOfTheExperimentAndMatchesExceptionsForInstance()
        {
            var mock = Substitute.For <IControlCandidate <int> >();

            mock.Control().Returns(x => { throw new InvalidOperationException(); });
            mock.Candidate().Returns(x => { throw new InvalidOperationException(); });
            const string experimentName = nameof(RunsBothBranchesOfTheExperimentAndMatchesExceptions);

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new Scientist(resultPublisher);

            var ex = Assert.Throws <AggregateException>(() =>
            {
                scientist.Experiment <int>(experimentName, experiment =>
                {
                    experiment.Use(mock.Control);
                    experiment.Try("candidate", mock.Candidate);
                });
            });

            Exception baseException = ex.GetBaseException();

            Assert.IsType <InvalidOperationException>(baseException);
            mock.Received().Control();
            mock.Received().Candidate();
            Assert.True(resultPublisher.Results <int>(experimentName).First().Matched);
        }
        public void DoesntRunCandidateIfIsEnabledAsyncReturnsFalse()
        {
            const int expectedResult = 42;

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new MyScientist(resultPublisher);

            var mock = Substitute.For <IControlCandidate <int> >();

            mock.Control().Returns(expectedResult);

            const string experimentName = "doesNotRunIfNotEnabled";

            var result = scientist.Experiment <int>(experimentName, experiment =>
            {
                experiment.Use(mock.Control);
                experiment.Try("candidate", mock.Candidate);
            });

            Assert.Equal(expectedResult, result);

            mock.DidNotReceive().Candidate();
            mock.Received().Control();
            Assert.False(resultPublisher.Results <int>(experimentName).Any());
        }
        public async Task RunsBothBranchesOfSimpleAsynchronousExperimentAndReportsFailure()
        {
            const string experimentName = nameof(RunsBothBranchesOfSimpleAsynchronousExperimentAndReportsFailure);

            var resultPublisher = new InMemoryResultPublisher();
            var science         = new Scientist(resultPublisher);

            var result = await science.ExperimentAsync <int>(experimentName, experiment =>
            {
                experiment.Use(() => Task.FromResult(42));
                experiment.Try(() => Task.FromResult(37));
            });

            Assert.Equal(42, result);
            Assert.False(resultPublisher.Results <int>(experimentName).First().Matched);
            Assert.True(resultPublisher.Results <int>(experimentName).First().Mismatched);
        }
        public void RunsBothBranchesOfTheExperimentAndReportsSuccessForInstance()
        {
            var mock = Substitute.For <IControlCandidate <int> >();

            mock.Control().Returns(42);
            mock.Candidate().Returns(42);
            const string experimentName = nameof(RunsBothBranchesOfTheExperimentAndReportsSuccess);

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new Scientist(resultPublisher);

            var result = scientist.Experiment <int>(experimentName, experiment =>
            {
                experiment.Use(mock.Control);
                experiment.Try("candidate", mock.Candidate);
            });

            Assert.Equal(42, result);
            mock.Received().Control();
            mock.Received().Candidate();
            Assert.True(resultPublisher.Results <int>(experimentName).First().Matched);
        }
        public async Task RunsBothBranchesOfTheExperimentAsyncAndReportsFailureForInstance()
        {
            var mock = Substitute.For <IControlCandidateTask <int> >();

            mock.Control().Returns(Task.FromResult(42));
            mock.Candidate().Returns(Task.FromResult(43));
            const string experimentName = nameof(RunsBothBranchesOfTheExperimentAsyncAndReportsFailure);

            var resultPublisher = new InMemoryResultPublisher();
            var scientist       = new Scientist(resultPublisher);

            var result = await scientist.ExperimentAsync <int>(experimentName, experiment =>
            {
                experiment.Use(mock.Control);
                experiment.Try("candidate", mock.Candidate);
            });

            Assert.Equal(42, result);
            await mock.Received().Control();

            await mock.Received().Candidate();

            Assert.False(resultPublisher.Results <int>(experimentName).First().Matched);
        }