Commit 55e4ddc
Changed files (15)
product
project
common
service
project.specifications
product/project/common/ActionCommand.cs
@@ -11,7 +11,7 @@ namespace mars.rover.common
this.command = command;
}
- public void run()
+ public virtual void run()
{
command();
}
product/project/presentation/CaptureUserInstructionsConsoleView.cs
@@ -26,7 +26,7 @@ namespace mars.rover.presentation
writer.WriteLine("enter commands to navigate rover:");
presenter.navigate_rover_using(reader.ReadLine());
}
- presenter.go();
+ presenter.process_output();
}
public void display(string location)
product/project/presentation/CaptureUserInstructionsPresenter.cs
@@ -1,4 +1,5 @@
using mars.rover.presentation.infrastructure;
+using mars.rover.service.application;
namespace mars.rover.presentation
{
@@ -33,7 +34,7 @@ namespace mars.rover.presentation
pump.run<NavigateRoverCommand, string>(navigation_commands);
}
- public void go()
+ public void process_output()
{
pump.run();
}
product/project/presentation/CreateMarsCommand.cs โ product/project/service/application/CreateMarsCommand.cs
@@ -2,11 +2,11 @@ using System;
using mars.rover.common;
using mars.rover.domain;
-namespace mars.rover.presentation
+namespace mars.rover.service.application
{
public class CreateMarsCommand : ParameterizedCommand<string>
{
- NASA nasa;
+ readonly NASA nasa;
public CreateMarsCommand(NASA nasa)
{
product/project/presentation/DeployRoverCommand.cs โ product/project/service/application/DeployRoverCommand.cs
File renamed without changes
product/project/Program.cs
@@ -6,6 +6,7 @@ using mars.rover.domain;
using mars.rover.presentation;
using mars.rover.presentation.infrastructure;
using mars.rover.presentation.model;
+using mars.rover.service.application;
namespace mars.rover
{
product/project/project.csproj
@@ -52,8 +52,8 @@
<Compile Include="presentation\infrastructure\CommandFactory.cs" />
<Compile Include="presentation\infrastructure\CommandPump.cs" />
<Compile Include="presentation\infrastructure\SynchronousCommandPump.cs" />
- <Compile Include="presentation\CreateMarsCommand.cs" />
- <Compile Include="presentation\DeployRoverCommand.cs" />
+ <Compile Include="service\application\CreateMarsCommand.cs" />
+ <Compile Include="service\application\DeployRoverCommand.cs" />
<Compile Include="presentation\infrastructure\SynchronousCommandProcessor.cs" />
<Compile Include="presentation\model\HeadingFactory.cs" />
<Compile Include="common\CallbackCommand.cs" />
@@ -72,7 +72,7 @@
<Compile Include="domain\Plateau.cs" />
<Compile Include="presentation\model\Navigation.cs" />
<Compile Include="domain\NASA.cs" />
- <Compile Include="presentation\NavigateRoverCommand.cs" />
+ <Compile Include="service\application\NavigateRoverCommand.cs" />
<Compile Include="presentation\Presenter.cs" />
<Compile Include="presentation\CaptureUserInstructionsPresenter.cs" />
<Compile Include="common\Specification.cs" />
@@ -84,6 +84,10 @@
<Compile Include="presentation\model\UnknownHeadingFactory.cs" />
<Compile Include="presentation\model\UnknownNavigation.cs" />
</ItemGroup>
+ <ItemGroup>
+ <Folder Include="service\domain\" />
+ <Folder Include="service\infrastructure\" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
product/project.specifications/domain/NASASpecs.cs
@@ -0,0 +1,29 @@
+using developwithpassion.bdd.contexts;
+using developwithpassion.bdd.mbunit;
+using developwithpassion.bdd.mbunit.standard.observations;
+using mars.rover.domain;
+using Rhino.Mocks;
+
+namespace specifications.domain
+{
+ public class NASASpecs
+ {
+ }
+
+ public class when_retrieving_the_last_deployed_rover : observations_for_a_sut_without_a_contract<NASA>
+ {
+ it should_return_the_last_deployed_rover = () => result.should_be_equal_to(rover);
+
+ context c =
+ () => { rover = MockRepository.GenerateMock<Rover>(new Coordinate(0), new Coordinate(0), an<Heading>()); };
+
+ because b = () =>
+ {
+ sut.deploy(rover);
+ result = sut.waiting();
+ };
+
+ static Rover rover;
+ static Rover result;
+ }
+}
\ No newline at end of file
product/project.specifications/presentation/infrastructure/CommandFactorySpecs.cs
@@ -0,0 +1,28 @@
+using developwithpassion.bdd.contexts;
+using developwithpassion.bdd.mbunit;
+using developwithpassion.bdd.mbunit.standard.observations;
+using mars.rover.common;
+using mars.rover.presentation.infrastructure;
+
+namespace specifications.presentation.infrastructure
+{
+ public class CommandFactorySpecs
+ {
+ }
+
+ public class when_creating_a_command_for_an_action : observations_for_a_sut_without_a_contract<CommandFactory>
+ {
+ it should_return_a_command_that_executes_the_action_when_invoked = () => was_executed.should_be_equal_to(true);
+
+ context c = () => { was_executed = false; };
+
+ because b = () =>
+ {
+ result = sut.create_for(() => was_executed = true);
+ result.run();
+ };
+
+ static Command result;
+ static bool was_executed;
+ }
+}
\ No newline at end of file
product/project.specifications/presentation/infrastructure/SynchronousCommandProcessorSpecs.cs
@@ -0,0 +1,38 @@
+using developwithpassion.bdd;
+using developwithpassion.bdd.contexts;
+using developwithpassion.bdd.mbunit.standard.observations;
+using mars.rover.common;
+using mars.rover.presentation.infrastructure;
+
+namespace specifications.presentation.infrastructure
+{
+ public class SynchronousCommandProcessorSpecs
+ {
+ }
+
+ public class when_running_a_series_of_commands_synchronously :
+ observations_for_a_sut_with_a_contract<CommandProcessor, SynchronousCommandProcessor>
+ {
+ it should_run_each_command = () =>
+ {
+ first.was_told_to(x => x.run());
+ second.was_told_to(x => x.run());
+ };
+
+ context c = () =>
+ {
+ first = an<Command>();
+ second = an<Command>();
+ };
+
+ because b = () =>
+ {
+ sut.add(first);
+ sut.add(second);
+ sut.run();
+ };
+
+ static Command first;
+ static Command second;
+ }
+}
\ No newline at end of file
product/project.specifications/presentation/infrastructure/SynchronousCommandPumpSpecs.cs
@@ -0,0 +1,55 @@
+using System;
+using developwithpassion.bdd;
+using developwithpassion.bdd.contexts;
+using developwithpassion.bdd.mbunit.standard.observations;
+using mars.rover.common;
+using mars.rover.presentation.infrastructure;
+using Rhino.Mocks;
+
+namespace specifications.presentation.infrastructure
+{
+ public class SynchronousCommandPumpSpecs
+ {
+ }
+
+ public class when_putting_a_command_on_the_command_processor :
+ observations_for_a_sut_with_a_contract<CommandPump, SynchronousCommandPump>
+ {
+ it should_place_the_correct_command_on_the_processor =
+ () => processor.received(x => x.add(Arg<Command>.Is.Anything));
+
+ context c = () =>
+ {
+ processor = the_dependency<CommandProcessor>();
+ registry = the_dependency<Registry<ParameterizedCommand<string>>>();
+ factory = the_dependency<CommandFactory>();
+ correct = an<Correct>();
+ incorrect = an<InCorrect>();
+ registry.is_told_to(x => x.all()).it_will_return(correct, incorrect);
+ };
+
+ because b = () => sut.run<Correct, string>("blah");
+
+ static CommandProcessor processor;
+ static Registry<ParameterizedCommand<string>> registry;
+ static CommandFactory factory;
+ static Correct correct;
+ static InCorrect incorrect;
+ }
+
+ public class InCorrect : ParameterizedCommand<string>
+ {
+ public void run_against(string item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public class Correct : ParameterizedCommand<string>
+ {
+ public void run_against(string item)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
product/project.specifications/presentation/CaptureUserInstructionsPresenterSpecs.cs
@@ -2,6 +2,8 @@ using developwithpassion.bdd;
using developwithpassion.bdd.contexts;
using developwithpassion.bdd.mbunit.standard.observations;
using mars.rover.presentation;
+using mars.rover.presentation.infrastructure;
+using mars.rover.service.application;
namespace specifications.presentation
{
@@ -9,14 +11,55 @@ namespace specifications.presentation
{
}
- public class when_initialized : observations_for_a_sut_without_a_contract<CaptureUserInstructionsPresenter>
+ public class concerns_for_presenter : observations_for_a_sut_without_a_contract<CaptureUserInstructionsPresenter>
{
- it should_wait_for_instructions_from_nasa = () => view.was_told_to(x => x.attach_to(sut));
+ context c = () =>
+ {
+ view = the_dependency<CaptureUserInstructionsView>();
+ pump = the_dependency<CommandPump>();
+ };
- context c = () => { view = the_dependency<CaptureUserInstructionsView>(); };
+ static protected CaptureUserInstructionsView view;
+ static protected CommandPump pump;
+ }
+
+ public class when_initializing_the_user_interface : concerns_for_presenter
+ {
+ it should_wait_for_instructions_from_the_user = () => view.was_told_to(x => x.attach_to(sut));
because b = () => sut.run();
+ }
+
+ public class when_the_user_specifies_the_boundary_of_the_plateau : concerns_for_presenter
+ {
+ it should_create_mars_with_the_boundary_coordinates = () => pump.run<CreateMarsCommand, string>(input);
+
+ context c = () => { input = "5 5"; };
+
+ because b = () => sut.provide_upper_right_coordinates(input);
+
+ static string input;
+ }
+
+ public class when_the_user_specifies_the_deployment_coordinates : concerns_for_presenter
+ {
+ it should_deploy_a_rover_to_those_coordinates = () => pump.run<DeployRoverCommand, string>(input);
+
+ context c = () => { input = "1 2 N"; };
+
+ because b = () => sut.deploy_rover_to(input);
+
+ static string input;
+ }
+
+ public class when_the_user_specifies_the_navigation_instructions : concerns_for_presenter
+ {
+ it should_navigate_the_rover_using_those_instructions = () => pump.run<NavigateRoverCommand, string>(input);
+
+ context c = () => { input = "lmlmlmlmm"; };
+
+ because b = () => sut.navigate_rover_using(input);
- static CaptureUserInstructionsView view;
+ static string input;
}
}
\ No newline at end of file
product/project.specifications/MockingExtensions.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Rhino.Mocks;
+using Rhino.Mocks.Interfaces;
+
+namespace specifications
+{
+ public static class MockingExtensions
+ {
+ public static IMethodOptions<R> is_told_to<T, R>(this T mocked_item, Function<T, R> action_to_perform) where T : class
+ {
+ return mocked_item.Stub(action_to_perform);
+ }
+
+ public static IMethodOptions<R> is_asked_for<T, R>(this T mock, Function<T, R> func) where T : class
+ {
+ return mock.Stub(func);
+ }
+
+ public static IMethodOptions<R> it_will_return<R>(this IMethodOptions<R> options, R item)
+ {
+ return options.Return(item);
+ }
+
+ public static IMethodOptions<IEnumerable<R>> it_will_return<R>(this IMethodOptions<IEnumerable<R>> options,
+ params R[] items)
+ {
+ return options.Return(items.AsEnumerable());
+ }
+
+ public static IMethodOptions<IEnumerable<R>> it_will_return_nothing<R>(
+ this IMethodOptions<IEnumerable<R>> options)
+ {
+ return options.it_will_return();
+ }
+
+ public static void it_will_throw<R>(this IMethodOptions<R> options, Exception item)
+ {
+ options.Throw(item);
+ }
+ }
+}
\ No newline at end of file
product/project.specifications/project.specifications.csproj
@@ -68,10 +68,15 @@
<Compile Include="common\DefaultRegistrySpecs.cs" />
<Compile Include="domain\CoordinateSpecs.cs" />
<Compile Include="domain\EastSpecs.cs" />
+ <Compile Include="domain\NASASpecs.cs" />
<Compile Include="domain\NorthSpecs.cs" />
<Compile Include="domain\MarsSpecs.cs" />
+ <Compile Include="MockingExtensions.cs" />
<Compile Include="presentation\CaptureUserInstructionsPresenterSpecs.cs" />
<Compile Include="domain\PositionSpecs.cs" />
+ <Compile Include="presentation\infrastructure\CommandFactorySpecs.cs" />
+ <Compile Include="presentation\infrastructure\SynchronousCommandProcessorSpecs.cs" />
+ <Compile Include="presentation\infrastructure\SynchronousCommandPumpSpecs.cs" />
<Compile Include="presentation\model\HeadingFactorySpecs.cs" />
<Compile Include="presentation\model\NavigationSpecs.cs" />
<Compile Include="ProgramSpecs.cs" />