рдпрд╣ рдХрд┐рддрдиреА рдмрд╛рд░ рд╣реБрдЖ рд╣реИ рдХрд┐ рдЬрдм рдЖрдк рдПрдХ рдХрд╛рд░реНрдпрд╢реАрд▓ рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕рдХреЗ рдХреЛрдб рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рдФрд░ рдХреНрдпрд╛ рдпрд╣ ... рдмреБрд░рд╛ рд╣реИ? рдФрд░ рдЖрдк рдРрд╕рд╛ рд╕реЛрдЪрддреЗ рд╣реИрдВ: "рдпрд╣ рдПрдХ рдкрд░реАрдХреНрд╖рд╛ рд╣реИ, рдЗрд╕реЗ рдРрд╕реЗ рд╣реА рдЫреЛрдбрд╝ рджреЗрдВ ..."ред рдирд╣реАрдВ,% рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо% рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рди рдЫреЛрдбрд╝реЗрдВред рдЯреЗрд╕реНрдЯ рд╕рд┐рд╕реНрдЯрдо рдХрд╛ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬреЛ рдХреЛрдб рд╕рдорд░реНрдерди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдпрд╣ рд╣рд┐рд╕реНрд╕рд╛ рднреА рд╕рдорд░реНрдерд┐рдд рд╣реИред рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рддрд░реАрдХреЗ рдирд╣реАрдВ рд╣реИрдВ (рд╣рдо рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд▓рд┐рдЦреЗрдВрдЧреЗ), рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдПрдХ рдЬреЛрдбрд╝реЗ рд╣реИрдВред

рд╣рдорд╛рд░реЗ рдбреЛрдбреЛ рджреЗрд╡рд╕реНрдХреВрд▓ рдбреЗрд╡рд▓рдкрд░ рд╕реНрдХреВрд▓ рдореЗрдВ, рд╣рдо рджреВрд╕рд░реЛрдВ рдХреЗ рдмреАрдЪ, рдПрдХ рдЕрдЪреНрдЫреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдорд╛рдкрджрдВрдб рдкрд░ рдкреНрд░рдХрд╛рд╢ рдбрд╛рд▓рддреЗ рд╣реИрдВ:
- reproducibility: рдПрдХ рд╣реА рдХреЛрдб рдФрд░ рдЗрдирдкреБрдЯ рдкрд░ рдкрд░реАрдХреНрд╖рдг рдЪрд▓рд╛рдиреЗ рд╕реЗ рд╣рдореЗрд╢рд╛ рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рд╣реЛрддрд╛ рд╣реИ;
- рдлреЛрдХрд╕: рдкрд░реАрдХреНрд╖рдг рдЧрд┐рд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рд░рдг рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП;
- рд╕рдордЭ: рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ, рдпрд╣рд╛рдБ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИред :)
рдЗрди рдХрд╕реМрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЖрдкрдХреЛ рдРрд╕реА рдкрд░реАрдХреНрд╖рд╛ рдХреИрд╕реА рд▓рдЧрддреА рд╣реИ?
[Fact] public void AcceptOrder_Successful() { var ingredient1 = new Ingredient("Ingredient1"); var ingredient2 = new Ingredient("Ingredient2"); var ingredient3 = new Ingredient("Ingredient3"); var order = new Order(DateTime.Now); var product1 = new Product("Pizza1"); product1.AddIngredient(ingredient1); product1.AddIngredient(ingredient2); var orderLine1 = new OrderLine(product1, 1, 500); order.AddLine(orderLine1); var product2 = new Product("Pizza2"); product2.AddIngredient(ingredient1); product2.AddIngredient(ingredient3); var orderLine2 = new OrderLine(product2, 1, 650); order.AddLine(orderLine2); var orderRepositoryMock = new Mock<IOrderRepository>(); var ingredientsRepositoryMock = new Mock<IIngredientRepository>(); var service = new PizzeriaService(orderRepositoryMock.Object, ingredientsRepositoryMock.Object); service.AcceptOrder(order); orderRepositoryMock.Verify(r => r.Add(order), Times.Once); ingredientsRepositoryMock.Verify(r => r.ReserveIngredients(order), Times.Once); }
рдореЗрд░реЗ рд▓рд┐рдП - рдмрд╣реБрдд рдмреБрд░рд╛ред
рдпрд╣ рд╕рдордЭ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рд╡реНрдпрд╡рд╕реНрдерд╛, рдЕрдзрд┐рдирд┐рдпрдо рдФрд░ рдореБрдЦрд░ рдмреНрд▓реЙрдХ рднреА рдЖрд╡рдВрдЯрд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ред
рдЕрдпреЛрдЧреНрдп: DateTime.Now рд╕рдВрдкрддреНрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдЕрдВрдд рдореЗрдВ, рдпрд╣ рдЦреБрд▓рд╛ рд╣реБрдЖ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЧрд┐рд░рд╛рд╡рдЯ рдХреЗ 2 рдХрд╛рд░рдг рд╣реИрдВ: рджреЛ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рддрд░реАрдХреЛрдВ рдкрд░ рдХреЙрд▓ рдХреА рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдирд╛рдордХрд░рдг рдЗрд╕ рд▓реЗрдЦ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдкрд░реЗ рд╣реИ, рдлрд┐рд░ рднреА рдореИрдВ рдирд╛рдо рдкрд░ рдзреНрдпрд╛рди рджреЗрддрд╛ рд╣реВрдВ: рдЗрд╕ рддрд░рд╣ рдХреЗ рдирдХрд╛рд░рд╛рддреНрдордХ рдЧреБрдгреЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреЗ рд╕рд╛рде, рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рдЬрдм рдкрд░реАрдХреНрд╖рдг рдХреЗ рдирд╛рдо рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдПрдХ рдмрд╛рд╣рд░реА рд╡реНрдпрдХреНрддрд┐ рддреБрд░рдВрдд рд╕рдордЭ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрд░реАрдХреНрд╖рдг рдЖрдо рддреМрд░ рдкрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдХреНрдпреЛрдВ рд╣реИред
рдпрджрд┐ рдЖрдк рд╕рд╣рдорддрд┐ рд╕реЗ рдкрд░реАрдХреНрд╖рд╛ рдХрд╛ рдирд╛рдо рдирд╣реАрдВ рджреЗ рд╕рдХрддреЗ рд╣реИрдВ, рддреЛ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдХреБрдЫ рдЧрдбрд╝рдмрдбрд╝ рд╣реИред
рдЪреВрдВрдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╕рдордЭ рд╕реЗ рдмрд╛рд╣рд░ рд╣реИ, рдЖрдЗрдП рдЖрдкрдХреЛ рдмрддрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕рдореЗрдВ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ:
- рд╕рд╛рдордЧреНрд░реА рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИред
- рдЕрд╡рдпрд╡реЛрдВ рд╕реЗ, рдЙрддреНрдкрд╛рдж (рдкрд┐рдЬреНрдЬрд╛) рдмрдирд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред
- рдЙрддреНрдкрд╛рджреЛрдВ рд╕реЗ рдПрдХ рдСрд░реНрдбрд░ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдПрдХ рд╕реЗрд╡рд╛ рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдЧреАрд▓реА рд╣реЛрддреА рд╣реИред
- рдЖрджреЗрд╢ рд╕реЗрд╡рд╛ рдХреА AcceptOrder рд╡рд┐рдзрд┐ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
- рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдВрдмрдВрдзрд┐рдд рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ Add рдФрд░ ReserveIngredients рдХреЗ рддрд░реАрдХреЛрдВ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред
рддреЛ рд╣рдо рдЗрд╕ рдкрд░реАрдХреНрд╖рд╛ рдХреЛ рдХреИрд╕реЗ рдмреЗрд╣рддрд░ рдмрдирд╛рддреЗ рд╣реИрдВ? рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╢рд░реАрд░ рдореЗрдВ рдЫреЛрдбрд╝рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдФрд░ рдЙрд╕рдХреЗ рд▓рд┐рдП, рдорд╛рд░реНрдЯрд┐рди рдлрд╛рдЙрд▓рд░ рдФрд░ рд░реЗрдмреЗрдХрд╛ рдкрд╛рд░реНрд╕рдиреНрд╕ рдЬреИрд╕реЗ рд╕реНрдорд╛рд░реНрдЯ рд▓реЛрдЧ
DSL (рдбреЛрдореЗрди рд╡рд┐рд╢рд┐рд╖реНрдЯ рднрд╛рд╖рд╛) рдХреЗ рд╕рд╛рде рдЖрдПред рдпрд╣рд╛рдВ рдореИрдВ рдЙрди рдбреАрдПрд╕рдПрд▓ рдкреИрдЯрд░реНрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реВрдВрдЧрд╛ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдбреЛрдбреЛ рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╣рдорд╛рд░реА рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдирд░рдо рдФрд░ рд░реЗрд╢рдореА рд╣реЛ рд╕рдХреЗрдВ, рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рд╣рд░ рджрд┐рди рдЖрддреНрдорд╡рд┐рд╢реНрд╡рд╛рд╕ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред
рдпреЛрдЬрдирд╛ рдпрд╣ рд╣реИ: рдкрд╣рд▓реЗ рд╣рдо рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╕рдордЭ рдореЗрдВ рд▓рд╛рдПрдБрдЧреЗ, рдлрд┐рд░ рд╣рдо рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрддрд┐рдХрд░рдг рдкрд░ рдХрд╛рдо рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдХреЗ рд╕рдорд╛рдкреНрдд рдХрд░реЗрдВрдЧреЗред рд╣рдордиреЗ рдЪрд▓рд╛рдИ ...
рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдирд┐рдкрдЯрд╛рди (рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдбреЛрдореЗрди рдСрдмреНрдЬреЗрдХреНрдЯ)
рдЪрд▓рд┐рдП рдСрд░реНрдбрд░ рдХреНрд░рд┐рдПрд╢рди рдмреНрд▓реЙрдХ рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред рдЖрджреЗрд╢ рджреЗрдирд╛ рдХреЗрдВрджреНрд░реАрдп рдбреЛрдореЗрди рд╕рдВрд╕реНрдерд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдо рдЖрджреЗрд╢ рдХрд╛ рд╡рд░реНрдгрди рдЗрд╕ рддрд░рд╣ рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╡реЗ рд▓реЛрдЧ рднреА рдЬреЛ рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВ рд▓реЗрдХрд┐рди рдбреЛрдореЗрди рд▓реЙрдЬрд┐рдХ рдХреЛ рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдХрд┐рд╕ рддрд░рд╣ рдХрд╛ рдСрд░реНрдбрд░ рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрд╡рдпрд╡реЛрдВ, рдкрд┐рдЬреНрдЬрд╛ рдФрд░ рдЕрдиреНрдп рдбреЛрдореЗрди рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдЕрдореВрд░реНрдд "рд╕рдВрдШрдЯрдХ 1" рдФрд░ "рдкрд┐рдЬреНрдЬрд╛ 1" рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдЫреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рдкрд╣рд▓рд╛ рдЙрдореНрдореАрджрд╡рд╛рд░ рд╕рд╛рдордЧреНрд░реА рд╣реИред рдЙрдирдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ: рдЙрдиреНрд╣реЗрдВ рдХрд┐рд╕реА рднреА рдЕрдиреБрдХреВрд▓рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдмрд╕ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдПрдХ рдХреЙрд▓ред рдпрд╣ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЕрд▓рдЧ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рд▓реЗ рдЬрд╛рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдирд╛рдо рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ рддрд╛рдХрд┐ рдпрд╣ рдбреЛрдореЗрди рд╡рд┐рд╢реЗрд╖рдЬреНрдЮреЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╣реЛ:
public static class Ingredients { public static readonly Ingredient Dough = new Ingredient("Dough"); public static readonly Ingredient Pepperoni = new Ingredient("Pepperoni"); public static readonly Ingredient Mozzarella = new Ingredient("Mozzarella"); }
рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдкрд╛рдЧрд▓ рд╕рдВрдШрдЯрдХ 1, рд╕рдВрдШрдЯрдХ 2 рдФрд░ рд╕рдВрдШрдЯрдХ 3 рдХреЗ рдмрдЬрд╛рдп, рд╣рдореЗрдВ рдЖрдЯрд╛, рдкреЗрдкрд░реЛрдиреА рдФрд░ рдореЛрдЬрд╝реЗрд░реЗрд▓рд╛ рдорд┐рд▓рд╛ред
рдЖрдорддреМрд░ рдкрд░ рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рдиреЗ рд╡рд╛рд▓реА рдбреЛрдореЗрди рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдбреЛрдореЗрди рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдбрд░
рдЕрдЧрд▓реА рдбреЛрдореЗрди рдЗрдХрд╛рдИ рдЙрддреНрдкрд╛рдж рд╣реИред рдЙрдирдХреЗ рд╕рд╛рде рд╕рдм рдХреБрдЫ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ: рдкреНрд░рддреНрдпреЗрдХ рдЙрддреНрдкрд╛рдж рдореЗрдВ рдХрдИ рдШрдЯрдХ рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рд╣рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЙрдиреНрд╣реЗрдВ рдЙрддреНрдкрд╛рдж рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред
рдпрд╣рд╛рдБ, рдЕрдЪреНрдЫрд╛ рдкреБрд░рд╛рдирд╛ рдмрд┐рд▓реНрдбрд░ рдкреИрдЯрд░реНрди рдХрд╛рдо рдЖрддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдЙрддреНрдкрд╛рдж рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рдирд┐рд░реНрдорд╛рдг рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:
public class ProductBuilder { private Product _product; public ProductBuilder(string name) { _product = new Product(name); } public ProductBuilder Containing(Ingredient ingredient) { _product.AddIngredient(ingredient); return this; } public Product Please() { return _product; } }
рдЗрд╕рдореЗрдВ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдирд┐рд░реНрдорд┐рдд рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░, рдПрдХ рдХрд╕реНрдЯрдо
Containing
рд╡рд┐рдзрд┐ рдФрд░ рдПрдХ рдЯрд░реНрдорд┐рдирд▓
Please
рд╡рд┐рдзрд┐ рд╢рд╛рдорд┐рд▓ рд╣реИред рдпрджрд┐ рдЖрдкрдХреЛ рдХреЛрдб рдХреЗ рд╕рд╛рде рд░рд╣рдирд╛ рдкрд╕рдВрдж рдирд╣реАрдВ рд╣реИ, рддреЛ рдЖрдк
Please
Now
рд╕рд╛рде рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдмрд┐рд▓реНрдбрд░ рдЬрдЯрд┐рд▓ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдФрд░ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИ рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИред рдХреЛрдб рдХреНрд▓реАрдирд░ рдФрд░ рдЕрдзрд┐рдХ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рдПрдХ рдЕрдЪреНрдЫреЗ рддрд░реАрдХреЗ рд╕реЗ, рдмрд┐рд▓реНрдбрд░ рдХреЛ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдХреЛрдб рдбреЛрдореЗрди рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рдХреЗ рдкрд╛рд╕ рд╕реНрдкрд╖реНрдЯ рд╣реЛред рдпрд╣ рдЙрди рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд┐рд▓реНрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд▓рд╛рдпрдХ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдХрд╛рдо рд╢реБрд░реВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред
рдЙрддреНрдкрд╛рдж рдмрд┐рд▓реНрдбрд░ рдЖрдкрдХреЛ рдбрд┐рдЬрд╝рд╛рдЗрди рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдЬреИрд╕реЗ:
var pepperoni = new ProductBuilder("Pepperoni") .Containing(Ingredients.Dough) .Containing(Ingredients.Pepperoni) .Please();
рдЖрдкрдХреЛ рдЙрди рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рдЕрдиреБрдХреВрд▓рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рднрд▓реЗ рд╣реА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реЛ, рдПрдХ рдмрд┐рд▓реНрдбрд░ рдмрдирд╛рдиреЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рд╡рд╕реНрддреБ ObjectMother
рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рдЙрддреНрдкрд╛рдж рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕рднреНрдп рд╣реЛ рдЧрдпрд╛ рд╣реИ,
new ProductBuilder
рдХреЗ рдбрд┐рдЬрд╛рдЗрдирд░ рдЕрднреА рднреА рдмрд╣реБрдд рдмрджрд╕реВрд░рдд рджрд┐рдЦрддреЗ рд╣реИрдВред ObjectMother (рдкрд┐рддрд╛) рдкреИрдЯрд░реНрди рдХреЗ рд╕рд╛рде рдЗрд╕реЗ рдареАрдХ рдХрд░реЗрдВред
рдкреИрдЯрд░реНрди 5 kopecks рдХреЗ рд░реВрдк рдореЗрдВ рд╕рд░рд▓ рд╣реИ: рд╣рдо рдПрдХ рд╕реНрдерд┐рд░ рд╡рд░реНрдЧ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдореЗрдВ рд╕рднреА рдмрд┐рд▓реНрдбрд░реЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░рддреЗ рд╣реИрдВред
public static class Create { public static ProductBuilder Product(string name) => new ProductBuilder(name); }
рдЕрдм рдЖрдк рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
var pepperoni = Create.Product("Pepperoni") .Containing(Ingredients.Dough) .Containing(Ingredients.Pepperoni) .Please();
ObjectMother рдХрд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдШреЛрд╖рдгрд╛рддреНрдордХ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдирдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдбреЛрдореЗрди рдореЗрдВ рдкреЗрд╢ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐
Create
рдЖрдИрдбреАрдИ рд╢рдмреНрдж рд▓рд┐рдЦрддреЗ рд╕рдордп рдЖрдк рдЦреБрдж рдмрддрд╛рдПрдВрдЧреЗ рдХрд┐ рдЖрдк рдЗрд╕ рдбреЛрдореЗрди рдореЗрдВ рдХреНрдпрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рд╣рдорд╛рд░реЗ рдХреЛрдб рдореЗрдВ, ObjectMother рдХреЛ рдХрднреА-рдХрднреА Not
Create
, рд▓реЗрдХрд┐рди
Given
рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдореБрдЭреЗ рджреЛрдиреЛрдВ рд╡рд┐рдХрд▓реНрдк рдкрд╕рдВрдж рд╣реИрдВред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдЕрдиреНрдп рд╡рд┐рдЪрд╛рд░ рд╣реИ - рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕рд╛рдЭрд╛ рдХрд░реЗрдВред
рдШреЛрд╖рд┐рдд рд░реВрдк рд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, ObjectMother рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдХреЛрдб рдХреНрд▓реАрдирд░ рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдирдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдбреЛрдореЗрди рдореЗрдВ рдбреАрд▓ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рдПрдЧрд╛ред
рдЙрддреНрдкрд╛рдж рдирд┐рдХрд╛рд▓рдирд╛
рдпрд╣ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЙрддреНрдкрд╛рджреЛрдВ рдХреЛ рдЕрднреА рднреА рдмрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрдЧрд╣ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕реАрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдЙрддреНрдкрд╛рдж рд╣реИрдВ, рдФрд░ рдЕрд╡рдпрд╡реЛрдВ рдХреА рддрд░рд╣, рдЙрдиреНрд╣реЗрдВ рдПрдХ рдЕрд▓рдЧ рд╡рд░реНрдЧ рдореЗрдВ рдПрдХрддреНрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдирд╣реАрдВ:
public static class Pizza { public static Product Pepperoni => Create.Product("Pepperoni") .Containing(Ingredients.Dough) .Containing(Ingredients.Pepperoni) .Please(); public static Product Margarita => Create.Product("Margarita") .Containing(Ingredients.Dough) .Containing(Ingredients.Mozzarella) .Please(); }
рдпрд╣рд╛рдВ рдореИрдВрдиреЗ рдХрдВрдЯреЗрдирд░ рдХреЛ
Products
рдирд╣реАрдВ, рдмрд▓реНрдХрд┐
Pizza
ред рдпрд╣ рдирд╛рдо рдкрд░реАрдХреНрд╖рдг рдкрдврд╝рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ "рдкреЗрдкреНрдкрд░реЛрдиреА рдПрдХ рдкрд┐рдЬреНрдЬрд╛ рдпрд╛ рд╕реЙрд╕реЗрдЬ?" рдЬреИрд╕реЗ рд╕рд╡рд╛рд▓реЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред
рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдбреЛрдореЗрди рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ, рдЙрддреНрдкрд╛рдж 1 рдЬреИрд╕реЗ рд╡рд┐рдХрд▓реНрдк рдирд╣реАрдВред
рдСрд░реНрдбрд░ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдбрд░ (рдкреАрдЫреЗ рд╕реЗ рдЙрджрд╛рд╣рд░рдг)
рдЕрдм рд╣рдо рдСрд░реНрдбрд░ рдмрд┐рд▓реНрдбрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд░реНрдгрд┐рдд рдкреИрдЯрд░реНрди рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрдм рд╣рдо рдмрд┐рд▓реНрдбрд░ рд╕реЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рдЙрд╕ рдЪреАрдЬрд╝ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рд╣реИ рдХрд┐ рдореИрдВ рдПрдХ рдЖрджреЗрд╢ рдХреИрд╕реЗ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ:
var order = Create.Order .Dated(DateTime.Now) .With(Pizza.Pepperoni.CountOf(1).For(500)) .With(Pizza.Margarita.CountOf(1).For(650)) .Please();
рд╣рдо рдЗрд╕реЗ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рд╣рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдСрд░реНрдбрд░ рдФрд░ рдСрд░реНрдбрд░ рд▓рд╛рдЗрди рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдбрд░реЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╕рдм рдХреБрдЫ рдЖрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдбрд░ рдХреЗ рд╕рд╛рде рдХреНрд░рд┐рд╕реНрдЯрд▓ рд╕реНрдкрд╖реНрдЯ рд╣реИред рдпрд╣рд╛рдБ рдпрд╣ рд╣реИ:
public class OrderBuilder { private DateTime _date; private readonly List<OrderLine> _lines = new List<OrderLine>(); public OrderBuilder Dated(DateTime date) { _date = date; return this; } public OrderBuilder With(OrderLine orderLine) { _lines.Add(orderLine); return this; } public Order Please() { var order = new Order(_date); foreach (var line in _lines) { order.AddLine(line); } return order; } }
рд▓реЗрдХрд┐рди
OrderLine
рд╕рд╛рде
OrderLine
рд╕реНрдерд┐рддрд┐ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ: рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯрд░реНрдорд┐рдирд▓ рдХреГрдкрдпрд╛ рд╡рд┐рдзрд┐ рдХреЛ рдпрд╣рд╛рдВ рдирд╣реАрдВ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░реА рдмрд╛рдд, рдмрд┐рд▓реНрдбрд░ рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рддреА рд╣реИ рди рдХрд┐ рд╕реНрдереИрддрд┐рдХ
Create
рдФрд░ рди рд╣реА рдмрд┐рд▓реНрдбрд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдгред рд╣рдо
implicit operator
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрд╣рд▓реА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░реЗрдВрдЧреЗ рдФрд░ рд╣рдорд╛рд░рд╛ рдмрд┐рд▓реНрдбрд░ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
public class OrderLineBuilder { private Product _product; private decimal _count; private decimal _price; public OrderLineBuilder Of(decimal count, Product product) { _product = product; _count = count; return this; } public OrderLineBuilder For(decimal price) { _price = price; return this; } public static implicit operator OrderLine(OrderLineBuilder b) { return new OrderLine(b._product, b._count, b._price); } }
рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рд╣рдореЗрдВ
Product
рд╡рд░реНрдЧ рдХреЗ рд▓рд┐рдП рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧреА:
public static class ProductExtensions { public static OrderLineBuilder CountOf(this Product product, decimal count) { return Create.OrderLine.Of(count, product) } }
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐рдпрд╛рдВ рдбреАрдПрд╕рдПрд▓ рдХреЗ рдорд╣рд╛рди рджреЛрд╕реНрдд рд╣реИрдВред рд╡реЗ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд╛рд░рдХреАрдп рддрд░реНрдХ рд╕реЗ рдПрдХ рдШреЛрд╖рдгрд╛рддреНрдордХ, рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рд╡рд┐рд╡рд░рдг рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдмрд╕ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред :)
рдЗрди рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░реАрдХреНрд╖рдг рдХреЛрдб рдорд┐рд▓рд╛:
[Fact] public void AcceptOrder_Successful() { var order = Create.Order .Dated(DateTime.Now) .With(Pizza.Pepperoni.CountOf(1).For(500)) .With(Pizza.Margarita.CountOf(1).For(650)) .Please(); var orderRepositoryMock = new Mock<IOrderRepository>(); var ingredientsRepositoryMock = new Mock<IIngredientRepository>(); var service = new PizzeriaService(orderRepositoryMock.Object, ingredientsRepositoryMock.Object); service.AcceptOrder(order); orderRepositoryMock.Verify(r => r.Add(order), Times.Once); ingredientsRepositoryMock.Verify(r => r.ReserveIngredients(order), Times.Once); }
рдпрд╣рд╛рдБ рд╣рдордиреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓рд┐рдпрд╛ рд╣реИ рдХрд┐ рд╣рдо "рдкрд░реА рдкрд░реА" рдХрд╣рддреЗ рд╣реИрдВред рдпрд╣ рддрдм рд╣реЛрддрд╛ рд╣реИ рдЬрдм рдЖрдк рдкрд╣рд▓реА рдмрд╛рд░ рдмреЗрдХрд╛рд░ рдХреЛрдб рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЗрд╕реЗ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдЬреЛ рдЖрдкрдиреЗ рдбреАрдПрд╕рдПрд▓ рдореЗрдВ рд▓рд┐рдЦрд╛ рд╣реИ рдЙрд╕реЗ рд▓рдкреЗрдЯрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдпрд╣ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реИ - рдХрднреА-рдХрднреА рдЖрдк рд╕реНрд╡рдпрдВ рдХрд▓реНрдкрдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рдХрд┐ C # рдХреНрдпрд╛ рд╕рдХреНрд╖рдо рд╣реИред
рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рдПрдХ рдЬрд╛рджреБрдИ рдкрд░реА рдЖ рдЧрдИ рд╣реИ рдФрд░ рдЖрдкрдХреЛ рдЕрдкрдиреА рдЗрдЪреНрдЫрд╛рдиреБрд╕рд╛рд░ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреА рдЧрдИ рд╣реИ, рдФрд░ рдлрд┐рд░ рдбреАрдПрд╕рдПрд▓ рдореЗрдВ рд▓рд┐рдЦреА рдЧрдИ рд╣рд░ рдЪреАрдЬ рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рдПрдХ рд╕реЗрд╡рд╛ рдмрдирд╛рдирд╛ (рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдкреИрдЯрд░реНрди)
рдЖрджреЗрд╢ рдХреЗ рд╕рд╛рде рдЕрдм рд╕рдм рдХреБрдЫ рдХрдореЛрдмреЗрд╢ рдЦрд░рд╛рдм рд╣реИред рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рдореЛрдХрд╛ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рдпрд╣рд╛рдВ рдпрд╣ рдХрд╣рдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рд╕реНрд╡рдпрдВ, рдЬрд┐рд╕реЗ рд╣рдо рд╡рд┐рдЪрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдкрд░реАрдХреНрд╖рд╛ рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдкрд░реАрдХреНрд╖рдг рджреГрдврд╝рддрд╛ рд╕реЗ рддрд░реАрдХреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝реЗ рд╣реБрдП рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ рдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рд▓рд┐рдЦреЗ рдЬрд╛рдПрдВ, рддреЛ рдмреЗрд╣рддрд░ рд╣реИ рдХрд┐ рдирд╣реАрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХрднреА-рдХрднреА рд╡реЗ рдЙрдкрдпреЛрдЧреА рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдХрднреА-рдХрднреА, рдЖрдк рдЙрдирдХреЗ рдмрд┐рдирд╛ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдирд┐рдореНрди рддрдХрдиреАрдХ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЗ рд▓рд┐рдП рдмрд┐рд▓реНрдХреБрд▓ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреА рд╣реИ, рдФрд░ рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдЪрд╛рдирдХ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдкрд╣рд▓реЗ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рдЖрдк рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗ рд░рд╛рдЬреНрдп рдХреА рдЬрд╛рдБрдЪ рдХрд░реЗрдВ, рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдирд╣реАрдВред
рдЗрд╕рд▓рд┐рдП, рдореИрдВ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдореЗрд░реА рдкрд░реАрдХреНрд╖рд╛ рдкрджреНрдзрддрд┐ рдореЗрдВ рдПрдХ рднреА рдореЛрдХ рдирд╣реАрдВ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ
PizzeriaService
рд╕рд░реНрд╡рд┐рд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд░реИрдкрд░
PizzeriaService
рдЬрд┐рд╕рдореЗрдВ рдореИрдВ рдЙрди рд╕рднреА рддрд░реНрдХреЛрдВ рдХреЛ рдХреВрдЯрдмрджреНрдз рдХрд░рддрд╛
PizzeriaService
рдЬреЛ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреА рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВ:
public class PizzeriaServiceTestable : PizzeriaService { private readonly Mock<IOrderRepository> _orderRepositoryMock; private readonly Mock<IIngredientRepository> _ingredientRepositoryMock; public PizzeriaServiceTestable(Mock<IOrderRepository> orderRepositoryMock, Mock<IIngredientRepository> ingredientRepositoryMock) : base(orderRepositoryMock.Object, ingredientRepositoryMock.Object) { _orderRepositoryMock = orderRepositoryMock; _ingredientRepositoryMock = ingredientRepositoryMock; } public void VerifyAddWasCalledWith(Order order) { _orderRepositoryMock.Verify(r => r.Add(order), Times.Once); } public void VerifyReserveIngredientsWasCalledWith(Order order) { _ingredientRepositoryMock.Verify(r => r.ReserveIngredients(order), Times.Once); } }
рдпрд╣ рд╡рд░реНрдЧ рд╣рдореЗрдВ рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдЕрднреА рднреА рдЗрд╕реЗ рдХрд┐рд╕реА рддрд░рд╣ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрд╕ рдмрд┐рд▓реНрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕реЗ рд╣рдо рдкрд╣рд▓реЗ рд╕реЗ рдЬрд╛рдирддреЗ рд╣реИрдВ:
public class PizzeriaServiceBuilder { public PizzeriaServiceTestable Please() { var orderRepositoryMock = new Mock<IOrderRepository>(); var ingredientsRepositoryMock = new Mock<IIngredientRepository>(); return new PizzeriaServiceTestable(orderRepositoryMock, ingredientsRepositoryMock); } }
рдлрд┐рд▓рд╣рд╛рд▓, рд╣рдорд╛рд░реА рдкрд░реАрдХреНрд╖рд╛ рдкрджреНрдзрддрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:
[Fact] public void AcceptOrder_Successful() { var order = Create.Order .Dated(DateTime.Now) .With(Pizza.Pepperoni.CountOf(1).For(500)) .With(Pizza.Margarita.CountOf(1).For(650)) .Please(); var service = Create.PizzeriaService.Please(); service.AcceptOrder(order); service.VerifyAddWasCalledWith(order); service.VerifyReserveIngredientsWasCalledWith(order); }
рдкрд░реАрдХреНрд╖рдг рд╡рд┐рдзрд┐ рдХреЙрд▓ рдХреЗрд╡рд▓ рдкрд░реАрдХреНрд╖рдг рдпреЛрдЧреНрдп рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рдХрд╛рд░рдг рдирд╣реАрдВ рд╣реИред рдпрд╣рд╛рдБ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
рдпрд╣рд╛рдБ рд╣рдорд╛рд░реЗ рджреАрдорд╛ рдкрд╛рд╡рд▓реЛрд╡ рдиреЗ рд╡рд┐рд░рд╛рд╕рдд рдХреЛрдб рдХреЗ рдЬрдЯрд┐рд▓ рд░реАрдлреИрдХреНрдЯрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рд╣реИред
рдкрд░реАрдХреНрд╖рдг рдпреЛрдЧреНрдп рд╕рдмрд╕реЗ рдХрдард┐рди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдХреЛ рдмрдЪрд╛рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИред рд╡реНрдпрд╡рд╣рд╛рд░ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдмрджрд╕реВрд░рдд рдХреЙрд▓ рдЪреЗрдХ рдХреЛ рд╕реБрдВрджрд░ рддрд░реАрдХреЛрдВ рдореЗрдВ рд▓рдкреЗрдЯрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред
рдЗрд╕ рдХреНрд╖рдг рдореЗрдВ, рд╣рдо рдкрд░реАрдХреНрд╖рдг рдХреА рд╕рдордЭ рдХреЛ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдкреНрдд рд╣реЛ рдЧрдПред рдпрд╣ рдЗрд╕реЗ рдкреНрд░рдЬрдирди рдпреЛрдЧреНрдп рдФрд░ рдХреЗрдВрджреНрд░рд┐рдд рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред
рд░реЗрдкреНрд░реЛрдбреНрдпреВрд╕рдмрд┐рд▓рд┐рдЯреА (рд╢рд╛рдмреНрджрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░)
рд▓рд┐рдЯрд░рд▓ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдкреИрдЯрд░реНрди рд╕реАрдзреЗ рддреМрд░ рдкрд░ рдкреНрд░рдЬрдирди рдХреНрд╖рдорддрд╛ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рд╣рдореЗрдВ рдорджрдж рдорд┐рд▓реЗрдЧреАред рдлрд┐рд▓рд╣рд╛рд▓ рд╣рдорд╛рд░реА рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо
DateTime.Now
рджрд┐рдирд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЖрджреЗрд╢ рджрд┐рдирд╛рдВрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рдЕрдЪрд╛рдирдХ рдХреБрдЫ рддрд╛рд░реАрдЦ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдСрд░реНрдбрд░ рд╕реНрд╡реАрдХреГрддрд┐ рдХрд╛ рддрд░реНрдХ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдорд╛рд░реЗ рд╡реНрдпрд╛рдкрд╛рд░ рддрд░реНрдХ рдореЗрдВ рд╣рдореЗрдВ рдХрдо рд╕реЗ рдХрдо рдХреБрдЫ рд╕рдордп рдХреЗ рд▓рд┐рдП рдСрд░реНрдбрд░ рд╕реНрд╡реАрдХреГрддрд┐ рдХреЗ 2 рддрд░реНрдХ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдирд╛ рд╣реЛрдЧрд╛,
if (order.Date > edgeDate)
рдЬреИрд╕реЗ рдЖрджреЗрд╢ред
if (order.Date > edgeDate)
рдЬрд╛рдБрдЪ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ рдХрд░рдирд╛ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЧрд┐рд░рд╛рд╡рдЯ рдХрд╛ рдореМрдХрд╛ рд╣реИ рдЬрдм рд╕рд┐рд╕реНрдЯрдо рдХреА рддрд╛рд░реАрдЦ рд╕реАрдорд╛ рд╕реЗ рдЧреБрдЬрд░рддреА рд╣реИред рд╣рд╛рдВ, рд╣рдо рдЬрд▓реНрджреА рд╕реЗ рдЗрд╕реЗ рдареАрдХ рдХрд░ рджреЗрдВрдЧреЗ, рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рджреЛ рдореЗрдВ рд╕реЗ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВрдЧреЗ: рдПрдХ рд╕реАрдорд╛ рддрд┐рдерд┐ рд╕реЗ рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдЧрд╛, рдФрд░ рджреВрд╕рд░реЗ рдХреЗ рдмрд╛рджред рдлрд┐рд░ рднреА, рдРрд╕реА рд╕реНрдерд┐рддрд┐рдпреЛрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрд╣рддрд░ рд╣реИ рдФрд░ рддреБрд░рдВрдд рд╕рднреА рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЛ рд╕реНрдерд┐рд░ рдмрдирд╛рдПрдВред
"рдФрд░ DSL рдХрд╣рд╛рдБ рд╣реИ?" - рдЖрдк рдкреВрдЫреЗрдВред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рддрд┐рдерд┐рдпрд╛рдВ рджрд░реНрдЬ рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
3.May(2019)
ред рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдХрд╛ рдпрд╣ рд░реВрдк рди рдХреЗрд╡рд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП, рдмрд▓реНрдХрд┐ рд╡реНрдпрд╡рд╕рд╛рдп рдХреЗ рд▓рд┐рдП рднреА рд╕рдордЭрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдПрдХ рдРрд╕реА рд╕реНрдЯреИрдЯрд┐рдХ рдХреНрд▓рд╛рд╕ рдмрдирд╛рдПрдВ
public static class DateConstructionExtensions { public static DateTime May(this int day, int year) => new DateTime(year, 5, day); }
рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рддрд╛рд░реАрдЦреЗрдВ рдЗрд╕ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХрдорд╛рддреНрд░ рдЪреАрдЬ рдирд╣реАрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдордиреЗ рдЙрддреНрдкрд╛рджреЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдЕрд╡рдпрд╡реЛрдВ рдХреА рдорд╛рддреНрд░рд╛ рдХрд╛ рдкрд░рд┐рдЪрдп рджрд┐рдпрд╛, рддреЛ рд╣рдо рдХреБрдЫ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдЬреИрд╕реЗ
42.Grams("flour")
ред
рдорд╛рддреНрд░рд╛рддреНрдордХ рд╡рд╕реНрддреБрдУрдВ рдФрд░ рддрд┐рдерд┐рдпреЛрдВ рдХреЛ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╡рд┐рд╕реНрддрд╛рд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдлреЛрдХрд╕
рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдХреНрдпреЛрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ? рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдХреЗрдВрджреНрд░рд┐рдд рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рдЕрднреА рднреА рд╕рдорд░реНрдерди рдХрд░рдирд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдиреНрд╣реЗрдВ рдХреЛрдб рдмрджрд▓рддреЗ рд╕рдордп рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдкреБрд░рд╛рдиреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рджреЗрдЦрдиреЗ рдкрд░ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рддрд░реНрдХ рдмрджрд▓рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдмрдбрд╝реЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА, рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рдХреА рдЧрдИ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рдЯреБрдХрдбрд╝реЗ рдХрд╛рдЯ рджреЗрдВред рдпрджрд┐ рдкрд░реАрдХреНрд╖рдг рдХреЗрдВрджреНрд░рд┐рдд рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдирд╛рдо рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХреЗрд╡рд▓ рдЕрдкреНрд░рдЪрд▓рд┐рдд рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╣рдЯрд╛рдиреЗ рдФрд░ рдирдП рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдПрдХ рдЕрдЪреНрдЫрд╛ рдбреАрдПрд╕рдПрд▓ рд╣реИ, рддреЛ рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рд╕рдорд╕реНрдпрд╛ рдирд╣реАрдВ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╣рдордиреЗ DSL рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдХреЛ 2 рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдХреЗ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рджрд┐рдпрд╛:
[Fact] public void WhenAcceptOrder_AddIsCalled() { var order = Create.Order .Dated(3.May(2019)) .With(Pizza.Pepperoni.CountOf(1).For(500)) .With(Pizza.Margarita.CountOf(1).For(650)) .Please(); var service = Create.PizzeriaService.Please(); service.AcceptOrder(order); service.VerifyAddWasCalledWith(order); } [Fact] public void WhenAcceptOrder_ReserveIngredientsIsCalled() { var order = Create.Order .Dated(3.May(2019)) .With(Pizza.Pepperoni.CountOf(1).For(500)) .With(Pizza.Margarita.CountOf(1).For(650)) .Please(); var service = Create.PizzeriaService.Please(); service.AcceptOrder(order); service.VerifyReserveIngredientsWasCalledWith(order); }
рджреЛрдиреЛрдВ рдкрд░реАрдХреНрд╖рдг рдЫреЛрдЯреЗ, рд╕реНрдкрд╖реНрдЯ, рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдФрд░ рдХреЗрдВрджреНрд░рд┐рдд рдереЗред
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЕрдм рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдирд╛рдо рдЙрд╕ рдЙрджреНрджреЗрд╢реНрдп рдХреЛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рд╡реЗ рд▓рд┐рдЦреЗ рдЧрдП рдереЗ рдФрд░ рдЕрдм рдХреЛрдИ рднреА рдбреЗрд╡рд▓рдкрд░ рдЬреЛ рдореЗрд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЖрдпрд╛ рдерд╛, рд╕рдордЭ рдЬрд╛рдПрдЧрд╛ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдХреНрдпреЛрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдЗрд╕ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИред
рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдзреНрдпрд╛рди рдЙрдиреНрд╣реЗрдВ рд╕рдорд░реНрдерд┐рдд рдмрдирд╛рддрд╛ рд╣реИред рдПрдХ рдЕрдЪреНрдЫреА рдкрд░реАрдХреНрд╖рд╛ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдФрд░ рдЕрдм, рдореИрдВ рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЪрд┐рд▓реНрд▓рд╛рддреЗ рд╣реБрдП рд╕реБрди рд╕рдХрддрд╛ рд╣реВрдВ, "рдпреВрд░рд╛, рдХреНрдпрд╛ рдмрдХрд╡рд╛рд╕ рдХрд░ рд░рд╣реЗ рд╣реИрдВ? рд╣рдордиреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдПрдХ рдЬреЛрдбрд╝реЗ рдХреЛ рд╕реБрдВрджрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд▓рд╛рдЦ рдХреЛрдб рд▓рд┐рдЦрд╛ рд╣реИ? " рд╣рд╛рдБ, рдмрд┐рд▓реНрдХреБрд▓ред рдЬрдмрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЗрд╡рд▓ рдХреБрдЫ рдкрд░реАрдХреНрд╖рдг рд╣реИрдВ, рдпрд╣ рдбреАрдПрд╕рдПрд▓ рдореЗрдВ рдирд┐рд╡реЗрд╢ рдХрд░рдиреЗ рдФрд░ рдЗрди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рдмрдирд╛рддрд╛ рд╣реИред рдПрдХ рдмрд╛рд░ рдЬрдм рдЖрдк рдбреАрдПрд╕рдПрд▓ рд▓рд┐рдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЧреБрдбрд╝рд┐рдпреЛрдВ рдХрд╛ рдЧреБрдЪреНрдЫрд╛ рдорд┐рд▓рддрд╛ рд╣реИ:
- рдирдП рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдЦреБрдж рдХреЛ 2 рдШрдВрдЯреЗ рддрдХ рд╕реЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдмрд╕ рд▓реЗ рдФрд░ рд▓рд┐рдЦреЛред
- рдЯреЗрд╕реНрдЯ рд╕рдордЭрдиреЗ рдФрд░ рдкрдврд╝рдиреЗ рдпреЛрдЧреНрдп рд╣реЛ рдЬрд╛рддреЗ рд╣реИрдВред рдкрд░реАрдХреНрд╖рдг рджреЗрдЦрдиреЗ рд╡рд╛рд▓рд╛ рдХреЛрдИ рднреА рдбреЗрд╡рд▓рдкрд░ рд╕рдордЭрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреНрдпреЛрдВ рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рдерд╛ рдФрд░ рдпрд╣ рдХреНрдпрд╛ рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИред
- рдирдП рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг (рдФрд░ рд╢рд╛рдпрдж рдбреЛрдореЗрди рдореЗрдВ) рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдиреЗ рдХреА рд╕реАрдорд╛ рдХрдо рд╣реЛ рдЧрдИ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ObjectMother рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдбреЛрдореЗрди рдореЗрдВ рдХреНрдпрд╛ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
- рдФрд░ рдЕрдВрдд рдореЗрдВ, рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдХреЛрдб рдЕрдзрд┐рдХ рд╕рдорд░реНрдерд┐рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рдирдореВрдирд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдФрд░ рдкрд░реАрдХреНрд╖рдг рдпрд╣рд╛рдВ рдЙрдкрд▓рдмреНрдз
рд╣реИрдВ ред