Série de trabalhos: Mock Objects

2 de maio, 2009

Estou fazendo dois trabalhos atualmente: sobre Mock Objects (como preparatório para Service Simulation, se tudo der certo) e sobre WSS. Por isso, e também para receber alguns inputs (que seriam muito bem vindos) vou postar algumas coisas da minha pesquisa aqui no blog. E nesse post explico o que são Mock Objects.

Mock Objects são objetos que simulam outros objetos. São principalmente usados em testes de unidade. Existem vários frameworks de Mock Objects mas pessoalmente prefiro o jMock. Abaixo mostro um exemplo de um teste de unidade usando-se TestNG 5.9 e jMock 2.5:

public class PublisherTest {
	private Mockery context = new Mockery();
 
	public PublisherTest() {
		context = new Mockery();
		// para podermos mockar uma classe
		context.setImposteriser(ClassImposteriser.INSTANCE);
	}
 
	@Test
	public void testOneSubscriberReceivesAMessage() {
		// configura mock
		Subscriber subscriber = context.mock(Subscriber.class);
		Expectations expect = new Expectations();
		String message = "message";
 
		// configura estado do objeto
		Publisher publisher = new Publisher();
		publisher.add(subscriber);
 
		// expectativas
		expect.never(subscriber).receive(message);
 
		context.checking(expect);
 
		// executa
		publisher.publish(message);
 
		// verifica
		context.assertIsSatisfied();
	}
 
}

Usamos mocks em cenários onde precisamos testar um objeto que depende de outros. Qual o problema de dependências? O objetivo dos testes de unidade é testar objetos em isolado, mas se usássemos um Subscriber real erros nele poderiam fazer falhar o teste do Publisher (ver figura abaixo). Por isso usamos mocks.

Teste usando-se objetos reais

Teste usando-se objetos reais

Teste usando-se mocks

Teste usando-se mocks

Com mocks podemos não só substituir algum objeto, mas também controlar todas as interações que são feitas com ele: verificar chamadas de métodos, valores de parâmetros, definir valores de retorno, etc. No código acima estamos por exemplo esperando uma chamada ao método receive do subscriber.

Dito o objetivo que motivou a criação dessa técnica, existem outros que vieram a ser supridos por mocks:

  • Abstrair camadas mais baixas do sistema, tanto por elas não estarem prontas quanto por querermos trabalhar offline.
  • Centralizar a configuração de estado no próprio mock ao invés de espalhá-las pelos testes de unidade.
  • Simular condições difíceis de reproduzir, como o lançamento de uma excessão mais esdrúxula ou um valor retorno raro.
  • Verificar mais rapidamente quando um erro ocorre (fail fast), indicando em que passo do comportamento esperado foi errado ao invés de apenas dizer que o estado final do objeto não condiz com o esperado.

Algo muito interessante vindo do uso de mocks é o Need-Driven Development (NDD), mas não pretendo falar dele aqui. Quando sair meu trabalho disponibilizo no blog, mas quem tiver curiosidade pode me escrever, é sempre bom trocar idéias :)

arquitetura, teste , , ,

Phishing do Orkut

30 de março, 2009

Acabei de receber um scrap de uma amiga com com o seguinte conteúdo:

add esse aki
http://www.orkut.com.br/Main#Profile.aspx?uid=81020294310883490

A autora era minha amiga mesmo, o host do email era realmente do orkut, o scrap realmente estava no meu scrapbook. Quando cliquei no link, abriu a tela de login do Orkut. Digitei usuário e senha, dei Enter e ai caiu numa página de erro. Foi só ai olhei o endereço, que estava:

http://0rkvlservicelogins.freehostia.com/Main-Community-aspx-cmm-8348041.html

Droga! Phishing! Entrei logo a conta do Google e mudei minha senha. Já entrei em contato com a freehostia que está hospedando esse site, espero que eles venham a bloquear o banco de dados dele antes que ele venha a resgatar as senhas.

Pensando em como isso poderia ter vindo a ocorrer só me veio uma coisa à cabeça: os Applications. Vendo no profile da minha amiga vi uma aplicação estranha:

Chat Alegria - Salas de Bate Papo

Isso me fez pensar algumas coisas em relação a segurança:

  1. Sobre a Web 2.0. Quando abrimos espaço para usuários criarem conteúdo nos portais estamos abrindo uma grande brecha na segurança: emprestamos o nome do portal junto com toda sua credibilidade para qualquer usuário usar. Esse caso específico (em que o usuário pôs um link com o conteúdo diferente de seu href para direcionar o atacado a outro domínio) foi endereçado pela Wiki pondo-se um simples simbolozinho do lado de links apontando para domínios externos. Isso é uma forma da Wiki lavar as mãos e consequentemente fazer o usuário ficar mais medroso (leia-se atento).
  2. Sistemas de SSO. Uso a conta do Google para várias coisas: blog, feed reader, calendário, documentos e email e tenho muita coisa importante, se de algum lado minha senha vazar pode ir tudo pro espaço. Um sistema de SSO deveria ter mecanismos de contenção de danos. Talvez identificação de padrões de uso, identificação de ações típicas de ataques ou simplesmente (e o Google não faz!!) verificar se a conta do usuário já possui sessão aberta, e possisvelmente combinações desses mecanismos.
  3. Padronização. Os applications do Orkut são construidos com a API OpenSocial que é uma tentativa da Google de criar uma interface comum para desenvolvimento de aplicações para redes sociais. Padronizações são importantes acontecem em todas as áreas de TI, mas geram também esse outro lado. A partir do momento que um padrão se difunde, uma aplicação que venha a ser construida com fins maléficos tem seu impacto maximizado através de todos os aderentes ao padrão.



Cuidado a todos!

EDIT:

O freehostia já me respondeu:

Hello,

We have suspended the reported account immediately. Thank you for the assistance.

Best Regards,
Miles
support@freehostia.com
http://www.freehostia.com

Wow! Que rápido!!

segurança

REST com RESTEasy - JAXB e RESTEasy Client

5 de fevereiro, 2009

Uma ótima apresentação sobre REST me fez querer escrever um pouco sobre. Mais especificamente sobre o RESTEasy, implemetação certificada JAX-RS da JBoss. No projeto que fiz para certificação JBoss Certified SOA Developer o usei bastante e quero falar de algumas interessantes funcionalidades dele. Primeiro algumas considerações sobre REST:

  1. RESTEasy é um framework para criação de RESTful Web Services, o que em algum senso já é uma desvirtuação de REST (tal como Roy Fielding definiu), que trata de recursos. O que tem haver um serviço RESTful que loga o usuário? (O que aliás abre uma sedutora brecha para quebrar outro conceito REST: o de statelessness) De agora em diante irei usar REST e RESTful Web Services indistintamente.
  2. REST não é uma alternativa a SOA! Na verdade podemos usar REST para implementar SOA com WOA. Confuso? REST é uma alternativa ao WS-*, podendo ser usado no lugar dele para implementar SOA. A implementação RESTful de SOA é chamada WOA, ou ROA (veja a página de TLAs), que é um subconjunto de SOA.

JAXB binding

RESTEasy possui suporte a marshalling/unmarshalling de classes usando JAXB. Sou péssimo para dar exemplos mas vamos lá…:

@Path("/")
public class Servico {
 
	@GET @Path("/tempo")
	@Produces("text/xml")
	public Tempo getTempo() {
		return new Tempo("Parcialmente nublado", 20.3);
	}
 
	@POST @Path("/literal")
	@Consumes("text/xml")
	public void setTempo(Tempo tempo) {
		System.out.format("Descrição: %s%n", tempo.getDescricao());
		System.out.format("Temperatura: %d%n", tempo.getTemperatura());
	}
}
 
// classe anotada com JAXB
@XmlRootElement
class Tempo {
	private String descricao;
	private Double temperatura;
 
	public Tempo() {}
 
	public Tempo(String nome, Double preco) {
		this.descricao = nome;
		this.temperatura = preco;
	}
 
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String nome) {
		this.descricao = nome;
	}
	public Double getTemperatura() {
		return temperatura;
	}
	public void setTemperatura(Double preco) {
		this.temperatura = preco;
	}
 
}

Na invocação de getTempo() RESTEasy vai ver que o tipo de retorno é o objeto Tempo e que ele está anotado com @XmlRootElement e vai fazer um marshalling dele. A anotação @Produces(”text/xml”) diz que a representação gerada deve ser XML. Quer que seja em JSON? Basta mudar para @Produces(”application/json”)!

Do mesmo jeito funciona o setTempo(). O parâmetro passados sem nenhuma anotação é interpretado como o corpo da requisição HTTP, que no caso é um objeto.

RESTEasy Client

Algo muito interessante que não é da especificação JAX-RS é o suporte a clients. Esses clients são proxies que transformam invocações Java em requisições HTTP. Para isso devemos criar uma interface com as mesmas assinaturas do nosso serviço e anotá-las:

public class Main {
	static {
		// precisa ser chamo uma única vez para registrar providers RESTEasy, scanear classes, etc
		 RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); // precisa ser chamado uma única vez para
	}
 
	public static void main(String args[]) {
 		 IServico client = ProxyFactory.create(IServico.class, "http://localhost:8080/<Context>");
 
		 Tempo tempo = client.getTempo();
		 tempo.setTemperatura(tempo.getTemperatura() + 5.0);
		 client.setTempo(tempo);
	}
}
 
interface IServico {
 
	@GET @Path("/tempo")
	@Produces("text/xml")
	public abstract Tempo getTempo();
 
	@POST @Path("/literal")
	@Consumes("text/xml")
	public abstract void setTempo(Tempo tempo);
}
 
// classe anotada com JAXB
@XmlRootElement
class Tempo {
	private String descricao;
	private Double temperatura;
 
	public Tempo() {}
 
	public Tempo(String nome, Double preco) {
		this.descricao = nome;
		this.temperatura = preco;
	}
 
	public String getDescricao() {
		return descricao;
	}
	public void setDescricao(String nome) {
		this.descricao = nome;
	}
	public Double getTemperatura() {
		return temperatura;
	}
	public void setTemperatura(Double preco) {
		this.temperatura = preco;
	}
 
}

Agora você deve ver no console:

Descrição: Parcialmente nublado
Temperatura: 34.000000

Precisamos a classe Tempo também apenas porque estamos usando JAXB. Tudo transparente, muito fácil agora fazer teste unitários de serviços RESTful!

JBoss, SOA , ,

Lançamento do JBossBrasil.ORG

19 de janeiro, 2009

Para quem nunca reparou, na minha sessão de links tem um badge do JBossBrasil. Já sou membro há um tempo e a comunidade já tem mais de 400 usuários mas o lançamento oficial será feito só agora, dia 21 de janeiro, em São Paulo. Para acompanhar o evento online o João Paulo detalhou no seu blog o que fazer.

Usa algum produto JBoss? Quer saber de eventos ou participar dos fóruns? Dê uma conferida: http://www.jbossbrasil.org.

Evento

Two components with the same name and precedence

8 de janeiro, 2009

Há um tempo atrás me pediram ajuda com a seguinte exceção:

java.lang.IllegalStateException: Two components with the same name and precedence - component name: authenticator, component classes: com.app.security.Authenticator, com.app.security.Authenticator
at org.jboss.seam.init.Initialization.addComponentDescriptor(Initialization.java:596)
at org.jboss.seam.init.Initialization.installScannedComponentAndRoles(Initialization.java:949)
at org.jboss.seam.init.Initialization.scanForComponents(Initialization.java:889)
at org.jboss.seam.init.Initialization.init(Initialization.java:701)
at org.jboss.seam.servlet.SeamListener.contextInitialized(SeamListener.java:35)

Essa exceção pode ocorrer, claro, quando existirem duas classes com o mesmo @Name, ou pode ocorrer num caso mais sutil. O Seam possui um modo de debug em que ele faz hot deploy de páginas Facelets e pages.xml’s. Projetos criados pelo seam-gen já vêm com esse modo habilitado:

<core:init debug="true"/>

Nesse modo o Seam usa um classloader próprio ao invés do classloader do container para carregar as classes. Ele faz isso criando um pasta WEB-INF/dev de onde carrega as classes. Isso não vale para EJB3 (então sem hot deploy de entity beans..) e as classes não serão visíveis para o container ou para outros projetos Seam (já que o Seam usa uma instância própria de classloader).

O problema é que de algum jeito o Seam (na verdade deve ser o JBoss Tools) se confunde em algumas situações e tenta fazer um novo deploy do componente, ao invés de fazer um redeploy. Com isso há um conflito de @Name. Não consegui identificar em que casos exatamente isso ocorre. Fazer um Clean, Build, etc não adianta porque a pasta dev não é mexida.

Bom, para resumir, basta apagar a pasta WEB-INF/dev ;)

JBoss, SOA

Novidades

13 de dezembro, 2008

Como devem ter percebido, mudei o para um novo layout, mudei também para um host free PHP, o 000webhost. Sobre o host, gostei muito, várias opções, limites altos, ótimo suporte. O único problema é que ele reinicia os bancos MySQL de hora em hora (cheiro de gambi??) retornando um erro de conexão PHP. Demora apenas alguns segundos, então uns refreshes no browser dão conta.

Agora posso mudar temas livremente, instalar plugins, usar meu domínio não só como um redirecionador. Estou também usando o FeedBurner, então vai ser necessário atualizar seus feed readers.

Os mais atentos ainda perceberam o novo bonequinho do lado direito. Cortei o cabelo =)

Sem categoria